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

让人想犯罪 __ 提交于 2020-05-29 02:35:05

问题


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?


回答1:


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



回答2:


GitHub has a feature called protected branches, which gives repository administrators the ability to disable force pushes to specific branches.

In addition to blocking force pushes, a protected branch can have required status checks.

for more information... Please check https://blog.github.com/2015-09-03-protected-branches-and-required-status-checks/




回答3:


Sooner or later someone merges the old dev into the new dev, bringing back all the mess with it.

This is a common problem when using the default git pull behavior. To avoid it, it's possible to configure git pull to use rebase by default instead of merge. That is, to rebase the current branch onto the remote branch instead of merging it:

git config pull.rebase interactive

From the git-config man page:

pull.rebase

When true, rebase branches on top of the fetched branch, instead of merging the default branch from the default remote when "git pull" is run. See "branch..rebase" for setting this on a per-branch basis.

When preserve, also pass --preserve-merges along to git rebase so that locally committed merge commits will not be flattened by running git pull.

When the value is interactive, the rebase is run in interactive mode.

NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see git-rebase(1) for details).

With that, whenever the remote branch is rewritten (with push -f), whoever is pulling is responsible for identifying and dropping the "old" commits during the rebase. This results in a clean history (i.e.: no merges of "old" versions) on each branch.



来源:https://stackoverflow.com/questions/52968175/how-to-prevent-a-specific-branch-from-being-merged-in-git

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!