问题
I have a Git pre-commit hook that prevents me from committing to master unless overridden, in order to encourage developing on branch.
However I would like to automatically allow merge commits to master. Is there a way to identify a merge commit from my pre-commit hook script? The script looks like this:
#!/bin/bash
BRANCH=`git branch --color=never| grep '^*'|cut -c3-`
if [ "${BRANCH}D" == "masterD" -a "${GIT_COMMIT_TO_MASTER}D" != "trueD" ]
then
echo "Commit directly to master is discouraged."
echo "If you want to do this, please set GIT_COMMIT_TO_MASTER=true and then commit."
exit 1
fi
SOLVED: For anyone looking for a cut-and-paste, the working version of this hook script is:
#!/bin/bash
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "${BRANCH}" == "master" -a "${GIT_COMMIT_TO_MASTER}" != "true" ]
then
if [ -e "${GIT_DIR}/MERGE_MODE" ]
then
echo "Merge to master is allowed."
exit 0
else
echo "Commit directly to master is discouraged."
echo "If you want to do this, please set GIT_COMMIT_TO_MASTER=true and then commit."
exit 1
fi
fi
回答1:
I put a few comments in, but the important one here is that in a pre-commit hook, the commit you're about to test does not yet exist, so you can't count its parents.
Here's what you do get:
If you're using
git commit --amend
to amend a merge commit, the pre-commit hook is run as usual, but it can't really detect that this is happening. The new commit will be a merge, but you can't tell.If you're using regular old
git commit
to create a non-merge commit, the fileMERGE_HEAD
will not exist in the git directory, and you can tell that this is not going to create a merge commit.If you're using
git commit
to finish off a conflicted merge, the fileMERGE_HEAD
will exist, and you can tell that this is going to create a merge commit.If you're running
git merge
and it succeeds on its own, it makes a new commit without using the pre-commit hook, so you don't even get invoked here.
Hence, if you're willing to allow git commit --amend
on merges to misfire, you can get close to what you want: just test for the existence of $GIT_DIR/MERGE_HEAD
to see if this is a git commit
that is finishing off a conflicted merge. (The use of $GIT_DIR
is a trick to make this work even if the commands are run outside the git tree. Git sets $GIT_DIR
so that in-hook git commands will work right.)
来源:https://stackoverflow.com/questions/29229247/how-can-i-allow-git-merge-commits-to-master-but-prevent-non-merge-commits