How can I get the merge head revision in my hook?
By using the environment variable GIT_REFLOG_ACTION
, which, in case of a merge, will be something like "merge mybranch
".
So "${GIT_REFLOG_ACTION#* }"
is enough to extract the branch name, even tough its content is supposed to be human-readable".
The following illustrates the use of "${GIT_REFLOG_ACTION#* }"
, while adding information on the nature of the pre-merge-commit
hook.
I thought a failed status would mean the merge is cancelled, but no:
exit 1
in that hook leaves the merge "in progress".
If you need to actually abort the merge, the hook has to call itself (in background) and wait one second (for the main hook process to exit, and for Git to deny the merge.
That second call should execute git merge --abort
#!/bin/bash
root="$(pwd)"
src="${GIT_REFLOG_ACTION#* }"
dst="$(git rev-parse --abbrev-ref HEAD)"
if [[ "${abort}" == 1 ]]; then
echo "Abort merge between '${src}' and '${dst}'"
git merge --abort </dev/null
cmd /d /c "exit"
exit 0
fi
echo "------"
echo "PRE-MERGE-COMMIT (${GIT_REFLOG_ACTION})"
echo "------"
# Should not happen, but test it just in case
if [[ "${src}" == "" ]]; then
echo "no merge in progress for this commit"
exit 1
fi
echo "Merge from '${src}' to '${dst}'"
# if you decide to prevent the merge:
export abort=1
"${0}" >&2 </dev/null &
exit 1
"${0}" >&2 </dev/null &
is the self-call. The pre-merge-commit
exits with status 1, git
acknowledges the merge is denied (but leaves it pending), and then, one second later, the same pre-merge-commit
script (called in background) aborts the merge for good.
The cmd /d /c "exit"
is used when the hook is triggered from a Windows CMD session in order to force the CMD prompt to appear.
Otherwise the echo "Abort merge between '${src}' and '${dst}'"
is displayed... and you would need to type enter to find the prompt again (because that echo is done from a background process).