As many of you probably know, there can be only one hook type in git. If two update hooks need to be evaluated. The git admin is left with two unmanageable solutions:
exec
I am looking for an elegant solution (written in BASH),something like a folder hooks/update.d
or hooks/post-receive.d
that will allow the loosely coupling of hook evaluations. The chaining should stop as soon as a hook fails.
I actually found an acceptable solution written in perl at this URL http://blog.bluefeet.net/2011/08/chained-git-hooks
The problem: my server runs different versions of perl and I am getting perllib version mismatches. It fails.
Unfortunately, git doesn't automatically synchronize hooks between project contributors. I can set up git hooks for my own workflow, but I need some extra help to share them with the rest of my team. Fortunately, git hook synchronization is an easy (and in later versions of git, almost trivial) problem to solve.
Second, you can't force developers to create commits that look a certain way—you can only encourage them to do so. Maintaining hooks for a team of developers can be a little tricky because the . git/hooks directory isn't cloned with the rest of your project, nor is it under version control.
git/hooks is the folder that hosts our customized hooks, but this is not really helpful when we need to share these scripts within the team since this folder is not tracked by git. A good approach for solving this is adding all of our custom hooks on a separate folder inside our repository.
Git hooks are scripts that run automatically every time a particular event occurs in a Git repository. They let you customize Git's internal behavior and trigger customizable actions at key points in the development life cycle.
After further investigation and testing, here is a working solution:
create file .git/hooks/hook-chain
as follows
#!/bin/bash # # author: orefalo hookname=`basename $0` FILE=`mktemp` trap 'rm -f $FILE' EXIT cat - > $FILE for 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 fi done
Now link any hook that requires chaining, for instance
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.html data=$(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 $i done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With