如何防止狐步舞在“主"分支中合并? [英] How can I prevent foxtrot merges in my 'master' branch?

查看:98
本文介绍了如何防止狐步舞在“主"分支中合并?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

狐步步合并是起源/主"作为第二(或更高)父级合并的合并,如下所示:

提交'D'是foxtrot合并,因为'origin/master'是其第二个父级.请注意,此时来自源/主服务器"的第一父级历史记录如何包含提交"B".

但是在我的git repo中,我需要所有涉及"origin/master"的合并,以将"origin/master"保持为第一父级.不幸的是,当git评估提交是否符合快速转发条件时,它并不关心父顺序.这会导致我的master分支上的第一个父级历史记录有时丢失以前曾经存在的提交(例如,"git log --first-parent"的输出).

按先前图的提交'D'时,会发生以下情况:

如何防止这种推动?推动狐步合并后,起源/主"的第一父级历史记录不再包含提交"B"!

很明显,实际上没有丢失任何提交或工作,只是在我的环境中,我确实需要"git log --first-parent"作为稳定的累积提交记录-如果您愿意,可以使用一种写一次"Read-Many"(WORM)数据库.我有一些脚本和进程使用"git log --first-parent"来生成变更日志和发行说明,以及管理我的票务系统(JIRA)中的票证过渡.Foxtrot的合并破坏了我的脚本!

我可以在git存储库中安装某种预接收钩子,以防止foxtrot合并被推送吗?

p.s.此stackoverflow问题中的提交图是使用

它将通过推和Bitbucket Server UI中的合并"按钮来阻止foxtrot合并.即使许可证已过期,它也会这样做,从而使保护第一父挂钩"成为较大附件的免费组件.

以下是我的 Bit-Booster 的示例预先接收钩子:

  $ git pull$ git push远程:***被保护-第一亲"挂钩拒绝***偏僻的:remote:不允许合并[1f70043b34d3].*当前*母版必须出现远程:在后续提交的第一个父级"位置.看看如何远程:主机正在合并到错误的一侧(不是作为第一父级),请尝试以下操作:偏僻的:远程:git show --graph -s --pretty ='%h%d%n'\远程:1f70043b34d3 1f70043b34d3〜1原始/主设备偏僻的:远程:要解决,有两种传统解决方案:偏僻的:远程:1.(首选)重新建立分支机构:偏僻的:远程:git rebase原始/主远程:git push origin master偏僻的:远程:2.按照正确的方向重做合并:偏僻的:远程:git checkout master远程:git reset --hard origin/master远程:git merge --no-ff 1f70043b34d3eaedb750〜1远程:git push origin master偏僻的: 

有关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.

这篇关于如何防止狐步舞在“主"分支中合并?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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