serverside git restrict branch creation to specific users

121 views Asked by At

I'm thinking this needs to be done with some type of git hook.

On our central git server (where everybody merges to) - we have special (reserved) branch names, for example: any branch starting with RELEASE_ shall only be made by the CM team members as part of a formal release process.

I also need to block anyone from accidently commiting to that branch once it is created, ie: once a RELEASE has been made that RELEASE branch shall be read only in some form

This is not for malicious reasons, its just to stop stupid mistakes - we are all human and damn, shit happens just want to avoid and stop stupid mistakes before they bite the team in the ass and we have problems.

My question is, what GIT rule or hook can I create that will prevent this type of mistake from happening. And can this be worked around with a 'force push'? (this is why I am thinking the server side is where it needs to be enforced)

If this is possible, can you point met to an example? (This is not a hard thing to do with SVN - where we are comming from, and the powers that be are asking this question of me and I can't answer that yet)

NOTE: I think this really needs to be on the server side, reason: The hook needs to support all users, both windows and linux and I dont' want somebody to try to fix/upgrade/whatever these types of security hooks on accident... (that stuff never happens right...)

1

There are 1 answers

6
jthill On

You can do it with a pre-receive and either use ssh (or other OS-mediated) identities or if you need real security use signed commits, but the real source of awkwardness here is in your existing workflow: it's designed to fit within constraints that no longer apply.

Still, it's not hard to make Git work within those constraints, and probably a lot harder to get your to team adopt a new, unfamiliar workflow, so here's my seed pre-receive for vetting inbound commits:

#!/bin/bash --
# pre-receive hook to vet all inbound commits not in existing history

# collect all non-deleted tips, *[^0]* is any string w/ a nonzero
while read old new ref; do
    incoming+=("$old $new $ref")
    [[ $new = *[^0]* ]] && news="$news $new"
done

# vet each commit, id's via here-doc to keep shell environ access
while read commit; do
    check $commit here || hookrc=1
done <<EOD
$(  git rev-list $news --not --all  )
EOD

exit $hookrc

and it's easy enough to extend that in any direction you please. Use ssh for pushes that might need authorization and a workable idea is

if [[ $ref = refs/heads/RELEASE_* && ! -w update-release ]]
then hookrc=1; echo updating $ref needs authorization $USER does not have
fi

where you control updates on those refs by controlling write access to that file in the repo. Add authorized users to the file's group or acl, done.

But it's even easier to give each team a repo they administer themselves. The release team has a release repo, they can fetch anything they want to it and call it what they want, but nobody else can update it at all. The QA team has an incoming repo to which anyone can push and they control integration testing based off what shows up there. None of that needs to be cluttering up the main project repo, it's for the really important stuff, currently-shipping release tags and the maintenance-base tip.