I would like to protect my git repository so only non master branches can be overwritten. Is there a way to protect only selected branches?
You can use GitEnterprise to setup per-branch permissions (admin) to block non-fastforward pushes using fine-grained access permission.
And git config --system receive.denyNonFastForwards true
will simply do the job if you need to block history changing for all branches.
Here is a modification of the Tanu Kaskinen script to allow for wildcarding of branch names. We use branches with names starting with "d/" to designate "development" branches. I wanted a way to allow non-fast-forward updates for these d/ branches:
refs/heads/*,commit)
# branch
# git rev-list doesn't print anything on fast-forward updates
if [[ $(git rev-list "$newrev".."$oldrev") ]]; then
branch=${refname##refs/heads/}
if [[ "$branch" =~ ^d/ ]] ; then
echo "Non-fast-forward update allowed on d/ branch"
nonfastforwardallowed="true";
else
#look for a specific config setting
nonfastforwardallowed=$(git config --bool hooks.branch."$branch".allownonfastforward)
fi
if [ "$nonfastforwardallowed" != "true" ]; then
echo "hooks/update: Non-fast-forward updates are not allowed for branch $branch"
exit 1
fi
fi
This SO answer will give you what you're looking for. Just edit it to apply to the master branch instead:
#!/bin/sh
# lock the master branch for pushing
refname="$1"
if [ "$refname" = "refs/heads/master" ]
then
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
echo "You cannot push to the master branch."
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
exit 1
fi
exit 0
Update:
This will prevent all pushes to the master branch, including fast-forward.
You can prevent non-fast-forward updates by configuring denyNonFastForwards
git config --system receive.denyNonFastForwards true
But it applies for all branches. For more info please refer ProGit
I think it depends on what you use on server side to access your repository. There are some server applications which support per-branch permissions, like Gerrit or Gitlab (however, i'm not sure if Gitlab supports your usecase). Gerrit supports it, since i use a similiar workflow in my company.
Maybe Gitolite also supports it (that's what Gitlab uses under the hood), which is easier to setup, but doesn't have a webinterface like Gerrit or Gitlab.
Additional comment: GitEnterprise, as suggested, is also a good solution, my suggestions however are suitable, if you have your own server (which is common in many companies).
If you would be allowed to modify your server, then this will enable fast-forwarding on server.
ssh ip 'echo $"[receive]
denyDeletes = false
denyNonFastForwards = false" >> /path/to/repo/config'
#then git push -f origin master