Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disallow branching from and merge of specific branches

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
like image 348
sdepold Avatar asked Nov 02 '12 13:11

sdepold


2 Answers

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.

like image 94
Michael Avatar answered Sep 21 '22 14:09

Michael


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:

  1. Ensure deploy is fully merged into review, so that later deploy can be fast-forwarded to review.
  2. Do any appropriate verification on review.
  3. Create and push a signed tag (git tag -s), using an authorized key, for the contents of review.
  4. Fast-forward 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>.

like image 37
Jamey Sharp Avatar answered Sep 21 '22 14:09

Jamey Sharp