Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| git_hooks [2019/02/19 09:34] – [Default hook installation for a new repository] rpjday | git_hooks [2019/02/19 11:10] (current) – [Default hook installation for a new repository] rpjday | ||
|---|---|---|---|
| Line 9: | Line 9: | ||
| * client-side | * client-side | ||
| * server-side | * server-side | ||
| + | |||
| + | Note that hooks can get their arguments from any combination of: | ||
| + | |||
| + | * the environment | ||
| + | * command-line arguments | ||
| + | * stdin | ||
| ===== Default hook installation for a new repository ===== | ===== Default hook installation for a new repository ===== | ||
| Line 26: | Line 32: | ||
| * '' | * '' | ||
| - | These are sample scripts supplied by Git that you can use as is, or customize to taste. In order to activate such scripts: | + | These are sample scripts supplied by Git that you can use as is, or customize to taste. In order to activate such scripts |
| * Make sure they are marked as executable. | * Make sure they are marked as executable. | ||
| - | * Remove the '' | + | * Remove the '' |
| - | ===== Properties of hooks ===== | + | ===== Where hooks are effectively run ===== |
| - | * They must be marked executable in order to be active. | + | From '' |
| - | * They normally live in '' | + | |
| - | * Running '' | + | |
| - | * Hooks can get their arguments via the environment, | + | |
| - | + | ||
| - | ===== Supporting code ===== | + | |
| - | + | ||
| - | ==== run_commit_hook() ==== | + | |
| < | < | ||
| - | int run_commit_hook(int editor_is_used, const char *index_file, | + | Before Git invokes a hook, it changes its working directory to |
| - | { | + | either $GIT_DIR in a bare repository or the root of the working |
| - | | + | tree in a non-bare repository. An exception are hooks triggered |
| - | va_list args; | + | during a push (pre-receive, update, post-receive, post-update, |
| - | int ret; | + | push-to-checkout) which are always executed in $GIT_DIR. |
| - | + | ||
| - | argv_array_pushf(& | + | |
| - | + | ||
| - | /* | + | |
| - | * Let the hook know that no editor will be launched. | + | |
| - | */ | + | |
| - | if (!editor_is_used) | + | |
| - | argv_array_push(& | + | |
| - | + | ||
| - | va_start(args, name); | + | |
| - | ret = run_hook_ve(hook_env.argv,name, args); | + | |
| - | | + | |
| - | argv_array_clear(& | + | |
| - | + | ||
| - | return ret; | + | |
| - | } | + | |
| </ | </ | ||
| - | + | ===== commit-related | |
| - | ==== builtin/ | + | |
| - | + | ||
| - | < | + | |
| - | static int prepare_to_commit(const char *index_file, | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | { | + | |
| - | struct stat statbuf; | + | |
| - | struct strbuf committer_ident = STRBUF_INIT; | + | |
| - | int commitable; | + | |
| - | struct strbuf sb = STRBUF_INIT; | + | |
| - | const char *hook_arg1 = NULL; | + | |
| - | const char *hook_arg2 = NULL; | + | |
| - | int clean_message_contents = (cleanup_mode != COMMIT_MSG_CLEANUP_NONE); | + | |
| - | int old_display_comment_prefix; | + | |
| - | + | ||
| - | /* This checks and barfs if author is badly specified */ | + | |
| - | determine_author_info(author_ident); | + | |
| - | + | ||
| - | if (!no_verify && run_commit_hook(use_editor, | + | |
| - | return 0; | + | |
| - | + | ||
| - | ... snip ... | + | |
| - | + | ||
| - | if (run_commit_hook(use_editor, | + | |
| - | git_path_commit_editmsg(), | + | |
| - | return 0; | + | |
| - | + | ||
| - | if (use_editor) { | + | |
| - | struct argv_array env = ARGV_ARRAY_INIT; | + | |
| - | + | ||
| - | argv_array_pushf(& | + | |
| - | if (launch_editor(git_path_commit_editmsg(), | + | |
| - | fprintf(stderr, | + | |
| - | _(" | + | |
| - | exit(1); | + | |
| - | } | + | |
| - | argv_array_clear(& | + | |
| - | } | + | |
| - | + | ||
| - | if (!no_verify && | + | |
| - | run_commit_hook(use_editor, | + | |
| - | return 0; | + | |
| - | } | + | |
| - | + | ||
| - | return 1; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | < | + | |
| - | int cmd_commit(int argc, const char **argv, const char *prefix) | + | |
| - | { | + | |
| - | const char *argv_gc_auto[] = {" | + | |
| - | static struct wt_status s; | + | |
| - | static struct option builtin_commit_options[] = { | + | |
| - | + | ||
| - | ... snip ... | + | |
| - | + | ||
| - | run_commit_hook(use_editor, | + | |
| - | if (amend && !no_post_rewrite) { | + | |
| - | commit_post_rewrite(current_head, | + | |
| - | } | + | |
| - | if (!quiet) { | + | |
| - | unsigned int flags = 0; | + | |
| - | + | ||
| - | if (!current_head) | + | |
| - | flags |= SUMMARY_INITIAL_COMMIT; | + | |
| - | if (author_date_is_interesting()) | + | |
| - | flags |= SUMMARY_SHOW_AUTHOR_DATE; | + | |
| - | print_commit_summary(prefix, | + | |
| - | } | + | |
| - | + | ||
| - | UNLEAK(err); | + | |
| - | UNLEAK(sb); | + | |
| - | return 0; | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | ===== The client-side hooks ===== | + | |
| ==== pre-commit ==== | ==== pre-commit ==== | ||
| - | In a nutshell (from '' | + | From '' |
| < | < | ||
| - | This hook is invoked by git commit, and can be bypassed with | + | This hook is invoked by git commit(1), and can be bypassed with |
| the --no-verify option. It takes no parameters, and is invoked | the --no-verify option. It takes no parameters, and is invoked | ||
| before obtaining the proposed commit log message and making a | before obtaining the proposed commit log message and making a | ||
| Line 210: | Line 113: | ||
| # If there are whitespace errors, print the offending file names and fail. | # If there are whitespace errors, print the offending file names and fail. | ||
| - | </ | ||
| - | |||
| - | Here's the money command: | ||
| - | |||
| - | < | ||
| - | exec git diff-index --check --cached $against -- | ||
| </ | </ | ||
| Line 346: | Line 243: | ||
| This hook is meant primarily for notification, | This hook is meant primarily for notification, | ||
| the outcome of git commit. | the outcome of git commit. | ||
| + | </ | ||
| + | |||
| + | There is no sample script provided by Git; you're on your own here. | ||
| + | |||
| + | ===== Overriding the default hooks ===== | ||
| + | |||
| + | ==== git init ==== | ||
| + | |||
| + | When initializing a new repository, the template content used for the new repository comes from one of (in order of precedence): | ||
| + | |||
| + | * the '' | ||
| + | * the value of the '' | ||
| + | * the '' | ||
| + | * the contents of ''/ | ||
| + | |||
| + | ==== git clone ==== | ||
| + | |||
| + | When cloning a repository, the only way to override the installation of default hooks (and template content) is via the '' | ||
| + | ==== During normal operation ==== | ||
| + | |||
| + | From '' | ||
| + | |||
| + | < | ||
| + | core.hooksPath | ||
| + | By default Git will look for your hooks in the | ||
| + | $GIT_DIR/ | ||
| + | / | ||
| + | directory, e.g. / | ||
| + | $GIT_DIR/ | ||
| + | |||
| + | The path can be either absolute or relative. A relative | ||
| + | path is taken as relative to the directory where the hooks | ||
| + | are run (see the " | ||
| + | |||
| + | This configuration variable is useful in cases where you’d | ||
| + | like to centrally configure your Git hooks instead of | ||
| + | configuring them on a per-repository basis, or as a more | ||
| + | flexible and centralized alternative to having an | ||
| + | init.templateDir where you’ve changed default hooks. | ||
| </ | </ | ||