We have a master
branch where the released production code lives, a dev
branch where the code for the test server lives, and various feature branches (branched from master
) as each developer sees fit.
Over the course of time the dev
branch has diverged somewhat from master
. In addition, there are some incorrect merges there that mess up parts of the code. Several times already we have tried to reset (force-push) dev
to be the same as master
. To start over with a clean slate, so to say.
Unfortunately this does not last long. Sooner or later someone merges the old dev
into the new dev
, bringing back all the mess with it. I suspect this might even happen automatically, where a naive git pull
silently merges the old and new branch heads.
Is it possible to prevent this with a server-side commit hook? Something that would refuse to accept the git push
if the wrong commit is merged in?
Use git-reset or git merge --abort to cancel a merge that had conflicts. Please note that all the changes will be reset, and this operation cannot be reverted, so make sure to commit or git-stash all your changes before you start a merge.
On the command line, a simple "git merge --abort" will do this for you. In case you've made a mistake while resolving a conflict and realize this only after completing the merge, you can still easily undo it: just roll back to the commit before the merge happened with "git reset --hard " and start over again.
It's possible with Git Hooks. Put the following POC script to .git/hooks/pre-receive
on your remote (server-side) repository and give it right permission to execute.
Configure the branch you want to protect, for example master
$ git config hooks.protected-branch.refs master
File: .git/hooks/pre-receive
#!/bin/sh
read old_value new_value ref_name
refs=$(git config hooks.protected-branch.refs)
for ref in $refs; do
if [ "$ref_name" == "refs/heads/$ref" ]; then
if [ "$old_value" == "0000000000000000000000000000000000000000" ]; then
continue
fi
if ! git merge-base --is-ancestor "$ref_name" "$new_value"; then
echo "$ref_name is protected branch"
exit 1
fi
fi
done
When you try to reset master
by force-push, You will get similar output like this:
Counting objects: 12, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (12/12), 920 bytes | 153.00 KiB/s, done.
Total 12 (delta 4), reused 0 (delta 0)
remote: refs/heads/master is protected branch
To ../demo
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to '../demo
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