Chaining git hooks
After further investigation and testing, here is a working solution:
create file .git/hooks/hook-chain
as follows
#!/bin/bash## author: orefalohookname=`basename $0`FILE=`mktemp`trap 'rm -f $FILE' EXITcat - > $FILEfor hook in $GIT_DIR/hooks/$hookname.*do if test -x "$hook"; then# echo $hook cat $FILE | $hook "$@" status=$? if test $status -ne 0; then echo Hook $hook failed with error code $status exit $status fi fidone
Now link any hook that requires chaining, for instance
- ln -s hook-chain update
- ln -s hook-chain post-receive
finally, create the chains by renaming them as hookname
.action
-rwxr-xr-x. 1 git git 6710 functions -rwxr-xr-x. 1 git git 280 hook-chain -rwxr-xr-x. 1 git git 1524 post-mirror lrwxrwxrwx. 1 root root 10 post-receive -> hook-chain -rwxr-xr-x. 1 git git 8763 post-receive.1email -rwxr-xr-x. 1 git git 1745 post-receive.2github -rwxr-xr-x. 1 git git 473 post-upload-pack -rwxr-xr-x. 1 git git 346 pre-receive lrwxrwxrwx. 1 root root 10 update -> hook-chain -rwxr-xr-x. 1 git git 2975 update.1acl -rwxr-xr-x. 1 git git 328 update.2github
for instance, in the sample above, the update hook will run update.1acl followed by update.2github.
The post-receive hook with run post-receive.1email followed by post-receive.2github
For those who're not willing to click on every link in comments below other answer, here's a practically unmodified version of the script by @HenrikN:
#!/bin/bash# Runs all executable hookname-* hooks and exits after,# if any of them was not successful.## Based on# http://osdir.com/ml/git/2009-01/msg00308.htmldata=$(cat)exitcodes=()hookname=$(basename $0)# Run each hook, passing through STDIN and storing the exit code.# We don't want to bail at the first failure, as the user might# then bypass the hooks without knowing about additional issues.for hook in $GIT_DIR/hooks/$hookname-*; do test -x "$hook" || continue echo "$data" | "$hook" exitcodes+=($?)done# If any exit code isn't 0, bail.for i in "${exitcodes[@]}"; do [ "$i" == 0 ] || exit $idone
I created a shell script based on OP and Olivier Refalo posts (with some modifications):
https://gist.github.com/amirbawab/e9f42ef8d441316707d9b90777e5718b
The script will generate a hook files that will execute scripts inside $hook_file_name.d/$hook_file_name.*
For example: for commit-msg
hook, the script will generate commit-msg
file under .git/hooks
that will execute all script under commit-msg.d/
.
Files under commit-msg.d
should match the pattern commit-msg.*
to allow placing helper shell files in those folder without executing them.
Script usage: ./extend_git_hooks.sh [REPO_PATH]