GIT:我怎样才能防止我的'主'分支foxtrot合并? [英] GIT: How can I prevent foxtrot merges in my 'master' branch?

查看:274
本文介绍了GIT:我怎样才能防止我的'主'分支foxtrot合并?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

foxtrot合并是一种合并,其中'origin / master'合并为第二个(或更后)父代,如下所示:


$ b

提交'D'是foxtrot合并,是其第二位家长。请注意,来自origin / master的第一个父级历史记录此时包含提交B。



但是在我的git仓库中,我需要所有涉及'origin / master'的合并来保留'origin / master'作为第一个父项。不幸的是,git在评估提交是否符合快进的条件时并不关心父亲的顺序。这导致我的主分支上的第一个父历史记录有时会丢失曾经存在的提交(例如,输出git log --first-parent)。



以下是当从前面的图中提交'D'时发生的情况:



我怎样才能防止这种推动?在foxtrot合并被推送后,'origin / master'的第一个父亲历史不再包含提交'B'!

显然没有提交或工作实际上已经丢失,只是在我的环境中,我真的需要git log --first-parent作为提交的稳定累积记录 - 如果你愿意,可以使用一种一次写入多次读取(WORM )数据库。我有使用git log --first-parent生成更改日志和发行说明的脚本和流程,以及管理我的售票系统(JIRA)中的故障单转换。 Foxtrot合并正在破坏我的脚本!



是否有某种预接收钩子可以安装在我的git存储库中,以防止foxtrot合并被推入?



ps这个stackoverflow问题中的提交图是使用



它将通过推送和Bitbucket服务器UI中的合并按钮来阻止foxtrot合并。即使它的许可证已过期,它也会这样做,使得保护First-Parent Hook成为更大附加组件的免费组件。



以下是我的< a-href =https://marketplace.atlassian.com/plugins/com.bit-booster.bb =noreferrer> Bit-Booster 保护第一个家长预先收到勾手:

  $ git pull 
$ git push

remote:*** PUSH REJECTED BY Protect-First-Parent HOOK ***
remote:
remote:不允许合并[1f70043b34d3]。 *当前*主机必须出现
remote:在后续提交的first-parent位置。要看看
remote:master是如何合并到错误的一面的(不是第一父母),试试这个:
remote:
remote:git show --graph -s --pretty =' %h%d%n'\
remote:1f70043b34d3 1f70043b34d3〜1 origin / master
remote:
remote:要修复,有两种传统解决方案:
remote:
remote:1.(首选)rebase你的分支:
remote:
remote:git rebase origin / master
remote:git push origin master
remote:
远程:2.以正确的方向重新合并:
remote:
remote:git checkout master
remote:git reset --hard origin / master
remote:git merge --no-ff 1f70043b34d3eaedb750〜1
remote:git push origin master
remote:

更多foxtrot合并背景我写了一篇博文


A foxtrot merge is a merge where 'origin/master' merges in as a 2nd (or later) parent, like so:

Commit 'D' is a foxtrot merge because 'origin/master' is its 2nd parent. Notice how first-parent history from 'origin/master' contains commit 'B' at this moment.

But in my git repo I need all merges involving 'origin/master' to keep 'origin/master' as the 1st parent. Unfortunately git doesn't care about parent-order when it evaluates whether a commit is eligible for fast-forward. This causes the first parent history on my master branch to sometimes lose commits that used to be there (e.g., output of "git log --first-parent").

Here's what happens when commit 'D' from the earlier diagram is pushed:

How can I prevent this push? First-parent history of 'origin/master' no longer contains commit 'B' after the foxtrot merge is pushed!

Obviously no commits or work are actually lost, it's just that in my environment I really need "git log --first-parent" to be a stable accumulative record of commits - if you like, a kind of "Write-Once Read-Many" (WORM) database. I have scripts and processes that use "git log --first-parent" to generate changelogs and release notes, as well as to manage ticket transitions in my ticketing system (JIRA). Foxtrot merges are breaking my scripts!

Is there some kind of pre-receive hook I could install in my git repositories to prevent foxtrot merges from getting pushed?

p.s. The commit graphs in this stackoverflow question were generated using http://bit-booster.com/graph.html.

解决方案

The following pre-receive hook will block those:

#/bin/bash

# Copyright (c) 2016 G. Sylvie Davies. http://bit-booster.com/
# Copyright (c) 2016 torek. http://stackoverflow.com/users/1256452/torek
# License: MIT license. https://opensource.org/licenses/MIT
while read oldrev newrev refname
do
if [ "$refname" = "refs/heads/master" ]; then
   MATCH=`git log --first-parent --pretty='%H %P' $oldrev..$newrev |
     grep $oldrev |
     awk '{ print \$2 }'`

   if [ "$oldrev" = "$MATCH" ]; then
     exit 0
   else
     echo "*** PUSH REJECTED! FOXTROT MERGE BLOCKED!!! ***"
     exit 1
   fi
fi
done

If you're using Github / Gitlab / Bitbucket Cloud, you may need to look into creating some kind of call into their commit status apis (here's api docs for: bitbucket, github; not sure if gitlab has one), because you don't have access to the pre-receive hooks, and even if you did, you'd still have to deal with people clicking the "merge" button directly in the web ui of those products (in which case there is no "push").

With Bitbucket Server you can install the add-on I created.

Once it's installed you click "enable" on the "Protect First Parent Hook" in a given repository's "hook" settings:

It will block foxtrot merges via push and via the "merge" button in the Bitbucket Server UI. It does this even if its license is expired, making the "Protect First-Parent Hook" a free component of the larger add-on.

Here's an example of my Bit-Booster "Protect First Parent" pre-receive hook in action:

$ ​git pull
$ git push

remote: *** PUSH REJECTED BY Protect-First-Parent HOOK ***
remote: 
remote: Merge [1f70043b34d3] is not allowed. *Current* master must appear
remote: in the 'first-parent' position of the subsequent commit. To see how
remote: master is merging into the wrong side (not as 1st parent), try this:
remote: 
remote:   git show --graph -s --pretty='%h %d%n' \
remote:      1f70043b34d3 1f70043b34d3~1 origin/master
remote: 
remote: To fix, there are two traditional solutions:
remote: 
remote:   1. (Preferred) rebase your branch:
remote: 
remote:       git rebase origin/master
remote:       git push origin master
remote: 
remote:   2. Redo the merge in the correct direction:
remote: 
remote:       git checkout master 
remote:       git reset --hard origin/master 
remote:       git merge --no-ff 1f70043b34d3eaedb750~1
remote:       git push origin master
remote: 

For more background on foxtrot merges I wrote a blog post.

这篇关于GIT:我怎样才能防止我的'主'分支foxtrot合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆