Chaining git hooks Chaining git hooks git git

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]