Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent a specific branch from being merged in git?

Tags:

git

githooks

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?

like image 662
Vilx- Avatar asked Oct 24 '18 11:10

Vilx-


People also ask

How do I stop a branch from merging?

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.

How do you stop a git process from merging?

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.


Video Answer


1 Answers

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
like image 193
Gasol Avatar answered Sep 19 '22 08:09

Gasol