How can I add my pre-commit hook to an existing git repository
checking it out my colleagues have it instantly in place
Sept. 2015: That is not possible: a hook can be put in source control (you simply copy the script in your git repo), but it cannot be "automatically in place" (active) on clone/checkout: that would be way too dangerous, depending on what the hook is actually doing.
See also "Git remote/shared pre-commit hook"
You would still need to activate it, by adding a symlink (even on Windows) to the pre-commit hook present in the git repo.
Update Dec. 2016: the OP Calamity Jane mentions in the comments:
I solved it by now in symfony2 projects (and with others, it also should work) to have it as part of the
composer.json
.
So if a colleague is doing acomposer install
orcomposer update
, it is automatically placed in the correct place.
"scripts": { "dev-install": [ "bash setup_phpcs.sh" ] },
So on dev,
setup_phpcs.sh
is automatically called and that copies the hook from a folder in the repository to the right place.
And since the hook is part of the repository it can be easily updated and distributed.
As noted by Hi-Angel in the comments:
I figured that out: Emacs has
build-aux
dir with hooks, and, upon runningautogen.sh
, all hooks are copied from there.
If your repo is an npm app, you can add this nice lib as dependency: husky
package.json
..."devDependencies": { ... "husky": ">=4"},"husky": { "hooks": { "pre-commit": "npm test" }}
pre-commit
can be basically any command: if it ends with exit code 0, commit passes, otherwise commit is interrupted.
fyi information in the year 2019 there is also this option:
require this package: "brainmaestro/composer-git-hooks"
and add the following lines to your composer.yaml
"extra": { "hooks": { "commit-msg": [ "regex=\"^([A-Z]{2,4}-[0-9]{1,4}|(no-ticket|NO-TICKET)):[\\s]*.{10,}\"", "file=`cat $1`", "if ! [[ $file =~ $regex ]]; then", " echo \"ERROR - Commit message is wrong or too short. E.g. XXX-33: Description or no-ticket : Description\"", " exit 1", "fi" ], "pre-commit": [ "git status --porcelain | grep -e '^ [AM]\\(.*\\).php$' | cut -c 3- | while read line; do", "ROOT=`php -r \"echo __DIR__;\"`", "bin/php-cs-fixer fix -nq --config=$ROOT/.php_cs \"$line\";", "bin/phpcbf --standard=PSR2 --encoding=utf-8 -n -p \"$line\";", "git add \"$line\";", "done", "echo committing on branch $(git rev-parse --abbrev-ref HEAD)" ] }}
This is the example, which works for me. What it basically does is this:
Everytime you run "composer install" or "composer update" the hooks in .git/hooks are checked. If the hooks are already in place nothing happens. If they are missing, then the lines from above are parsed into the the hooks with a shebang at the beginning. They are then executed each time somebody is triggering a hook.
If you don't have big scripts that is IMO the better solution than copying scripts around.
Note: if you change the lines in the composer.json for the hooks you have to delete the respective hook first before you run "composer install" or nothing will change.