Is there a git hook or some other way to prohibit branching from and merging of specific branches. We want to make sure that we don't merge a "dirty" integration branch into our clean deployment branch.
The major goal is that people cannot execute something like this:
git checkout integration
git checkout -b major_problem_branch
or
git checkout deployment_or_hotfix_or_feature_branch
git merge integration
You can use branch permissions on the server by adding this to the config file in your bare repository:
[hooks]
allowedtomerge = user1,user2,user3
protectedbranches = master
That will allow user1, user2, and user3 to merge to master branch, but no one else.
Or you could create a pre-commit hook:
#!/bin/bash
if [[ `git symbolic-ref HEAD` == "refs/heads/master" ] -a ["$USER" != "user1"]] then
echo "You cannot commit in master!"
exit 1
fi
Then you have people that evaluate and allow changes to go forward.
Ideally, I would use a system that you like, for instance gerrit or assembla or github. They have nice ways of controlling a master branch through Merge Requests.
In general, you can't reliably prevent anyone from making changes in their local repositories. Unless you trust your developers to never make any mistakes (in which case you wouldn't need this), you have to run your checks in hooks on your server.
That means you can't count on preventing people from branching, and I'm not sure why you'd really want to anyway. What you can do is keep people from pushing work that hasn't been somehow "approved" into the server's deployment branch (which I'm going to call deploy
).
Now the first question is how to express that approval.
If you want a workflow where an authorized person has to review work before it's deployed, then I'd have the reviewer do these steps, if the work is currently living on a branch named review
:
deploy
is fully merged into review
, so that later deploy
can be fast-forwarded to review
.review
.git tag -s
), using an authorized key, for the contents of review
.deploy
to review
(git checkout deploy
, git merge --ff-only review
) and push it.If instead you want anyone to be able to deploy, but you want them to have to think about it first, you could do the same thing but relax the signature requirements. Or you could bless a particular branch (tested
, say) and require that all work be merged and pushed to tested
before being pushed to deploy
.
How can the server verify that this approval has been given for the protected deploy
branch? The basic plan is to use the update
hook to accept or reject ref-updates for refs/heads/deploy
according to the acceptance criteria you've decided on.
If you want a tag that satisfies particular criteria, like being signed by an approved key, then you can find all tags that point to the new object proposed for deployment using git for-each-ref refs/tags
. Remember to accept the update if any tag meets the criteria, or else sooner or later somebody's going to push a bad tag that blocks deployment. Verifying that the right key was used is left as an exercise for the reader, but gpg --no-default-keyring --keyring=approved.gpg
may help.
If you'll take any commit as long as somebody's tagged it, you can use git describe --exact-match <object>
. If you want to limit to tags with a particular name pattern, add --match <pattern>
. If you'll accept unannotated tags, add --tags
.
If you want work merged to a blessed branch before being merged to deployment, you can check that the output of git rev-parse tested
equals the proposed new object.
In all cases, you probably want to double-check that the push is a fast-forwarding push. You can check that git merge-base <old> <new>
equals <old>
.
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