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

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

问题描述

foxtrot 合并是一种合并,其中origin/master"合并为第二个(或更高版本)父级,如下所示:

Commit 'D' 是 Foxtrot 合并,因为 'origin/master' 是它的第二个父级.请注意此时来自origin/master"的第一父历史记录如何包含提交B".

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

这是推送上图中的提交D"时发生的情况:

如何防止这种推送?推送 Foxtrot 合并后,'origin/master' 的第一父级历史不再包含提交 'B'!

显然没有提交或工作实际上丢失,只是在我的环境中我真的需要git log --first-parent"作为提交的稳定累积记录 - 如果你喜欢,一种一次写入"Read-Many" (WORM) 数据库.我的脚本和流程使用git log --first-parent"来生成变更日志和发行说明,以及在我的票务系统 (JIRA) 中管理票证转换.Foxtrot 合并正在破坏我的脚本!

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

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

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

这是我的Bit-Booster保护第一父母"的示例" pre-receive hook in action:

$ git pull$ git push远程:*** 被 Protect-First-Parent HOOK 拒绝推送 ***偏僻的:远程:不允许合并 [1f70043b34d3].*当前*大师必须出现远程:在后续提交的第一父"位置.看看如何远程:master 合并到错误的一边(不是第一个父级),试试这个:偏僻的:远程:git show --graph -s --pretty='%h %d%n' 远程:1f70043b34d3 1f70043b34d3~1 原点/主偏僻的:远程:要修复,有两种传统的解决方案:偏僻的:远程:1.(首选)重新设置您的分支:偏僻的:远程:git rebase origin/master远程: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天全站免登陆