Putting git hooks into repository Putting git hooks into repository git git

Putting git hooks into repository


I generally agree with Scytale, with a couple additional suggestions, enough that it's worth a separate answer.

First, you should write a script which creates the appropriate symlinks, especially if these hooks are about enforcing policy or creating useful notifications. People will be much more likely to use the hooks if they can just type bin/create-hook-symlinks than if they have to do it themselves.

Second, directly symlinking hooks prevents users from adding in their own personal hooks. For example, I rather like the sample pre-commit hook which makes sure I don't have any whitespace errors. A great way around this is to drop in a hook wrapper script in your repo, and symlink all of the hooks to it. The wrapper can then examine $0 (assuming it's a bash script; an equivalent like argv[0] otherwise) to figure out which hook it was invoked as, then invoke the appropriate hook within your repo, as well as the appropriate user's hook, which will have to be renamed, passing all the arguments to each. Quick example from memory:

#!/bin/bashif [ -x $0.local ]; then    $0.local "$@" || exit $?fiif [ -x tracked_hooks/$(basename $0) ]; then    tracked_hooks/$(basename $0) "$@" || exit $?fi

The installation script would move all pre-existing hooks to the side (append .local to their names), and symlink all known hook names to the above script:

#!/bin/bashHOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"# assuming the script is in a bin directory, one level into the repoHOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooksfor hook in $HOOK_NAMES; do    # If the hook already exists, is executable, and is not a symlink    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local    fi    # create the symlink, overwriting the file if it exists    # probably the only way this would happen is if you're using an old version of git    # -- back when the sample hooks were not executable, instead of being named ____.sample    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hookdone


No, putting them into the repository is fine, I’d even suggest doing so (if they are useful for others as well). The user has to explicitly enable them (as you said, for example by symlinking), which is on one hand a bit of a pain, but protects users on the other hand from running arbitrary code without their consent.


Nowadays you can do the following to set a directory that is under version control to be your git hooks directory, e.g., MY_REPO_DIR/.githooks would be

git config --local core.hooksPath .githooks/

Still not directly enforceable but, if you add a note in your README (or whatever), this requires a minimum of effort on each developer's part.