压拉请求会破坏git的合并算法吗?


17

我目前在一家使用VSTS管理git代码的公司工作。Microsoft合并分支的“推荐”方法是进行“挤压合并”,这意味着该分支的所有提交都被压缩为一个合并了所有更改的新提交。

问题是,如果我在一个分支中对一个积压项目进行了一些更改,然后立即开始在另一个分支中对另一个积压项目进行更改,而这些更改取决于第一个分支的更改集怎么办?

我可以为该积压项目创建一个分支,并将其基于第一个分支。到目前为止,一切都很好。但是,当需要为我的第二个分支创建一个拉取请求时,第一个分支已经合并到master分支中了,因为它是作为壁球合并完成的,所以git会标记很多冲突。这是因为git看不到第二个分支所基于的原始提交,它只看到一个大壁球合并,因此为了合并第二个分支以掌握它,它尝试重播第一个分支的所有提交。壁球合并的顶部,引起很多冲突。

所以我的问题是,有什么办法可以解决这个问题(除了从不将一个功能分支从另一个功能分支上转移出去,这限制了我的工作流程),或者壁球合并只是打破了git的合并算法?

Answers:


15

使用Git,提交

  • 是一成不变的,
  • 并形成有向无环图。

压扁不合并提交。相反,它将记录一个新的提交以及来自其他多个提交的更改。变基类似于,但不合并提交。记录具有与现有提交相同的更改的新提交称为历史重写。但是由于现有提交是不可变的,因此应将其理解为“编写替代历史记录”。

合并尝试合并从共同祖先提交开始的两个提交历史记录(分支)的更改。

因此,让我们看看您的历史记录:

                                 F  feature2
                                /
               1---2---3---4---5    feature1 (old)
              /
-o---o---o---A---o---o---S          master

A是公共祖先,原始要素分支是1-5,新要素分支是F,S是压缩后的提交,其中包含与1-5相同的更改。如您所见,F和S的共同祖先是A。就git而言,S和1-5之间没有任何关系。因此,将master与S一侧合并,将feature2与1–5合并将发生冲突。解决这些冲突并不困难,但这是不必要的,繁琐的工作。

由于这些限制,有两种方法来处理合并/压缩:

  • 您可以使用历史记录重写,在这种情况下,您将获得代表相同更改的多个提交。这样,你会重订的第二个特点分支到压扁的承诺:

                                     F  feature2 (old)
                                    /
                   1---2---3---4---5    feature1 (old)
                  /
    -o---o---o---A---o---o---S          master
                              \
                               F'       feature2
    
  • 或者您不使用历史记录重写,在这种情况下,您可能会得到额外的合并提交:

                                     F  feature2
                                    /
                   1---2---3---4---5    feature1 (old)
                  /                 \
    -o---o---o---A---o---o-----------M  master
    

    当feature2和master合并时,公共祖先将提交5。

在这两种情况下,您都需要进行一些合并工作。这项工作并不取决于您选择上述两种策略中的哪一种。但是请确保

  • 分支是短暂的,以限制它们与主分支之间的偏移量,
  • 您可以定期将master合并到您的功能分支中,或在master上重新建立功能分支以使分支保持同步。

在团队中工作时,有助于协调当前正在做什么的人员。这有助于使正在开发的功能部件的数量保持较小,并可以减少合并冲突的数量。


2
您的答案似乎无法解决如果您先将壁球合并feature1到母版,然后再合并的问题feature2。在那种情况下,当git尝试feature1在压缩的提交之上重新应用提交时,第一种方法不会导致冲突,而第二种方法将允许git确定不需要合并那些提交吗?
Jez

@Jez压缩PR时,这正是发生的情况。最近,我不得不在OSS项目上手动重写PR(通过git clone回购并复制更改的文件!),因为我从一个分支分支出来,然后维护者压缩了第一个分支。在我的工作中,他们也做壁球合并。这意味着b在合并功能a之前,我无法使用依赖功能的功能a
扔掉帐户

1
难道这不是git设计的原本会令人讨厌的东西的令人讨厌的破坏吗?瞧,我看到像Microsoft和Github这样的各种组织实际上都在建议这些壁球合并,这对我来说似乎很愚蠢。
Jez

1
@Jez在原始方案中,是的,将特征2合并到主数据库中时会发生冲突,因为合并提交1-5将与S中的相同更改冲突。解决方案是重新设置特征2(解决方案1)或不使用压扁/重设基准全部(解决方案2)。
阿蒙(Amon)

壁球合并是否适合您取决于要在版本控制历史记录中记录的内容。如果功能分支有许多WIP提交,则压扁会将具有完整功能的单个大提交提交到master分支上。如果您希望保留Feature分支的所有中间提交,请使用重新基准化或合并。
阿蒙(Amon)

11

壁球合并中断了包含壁球删除的所有提交的任何分支的合并算法。换句话说,基础是病毒式的。如果要重新建立一个分支的基础,则需要重新建立依赖该分支的所有其他分支的基础。如果使用rerere,则无需再次手动解决在本地存储库中手动解决的任何合并冲突,但这对其他人解决的冲突没有帮助。

这就是我们这里不成文的规则的原因,只要没有其他人依赖您的功能分支,就可以进行压榨,这可能是90%的情况。否则,直接合并将帮助每个人避免问题。


一种既在主历史记录中同时包含挤压提交又保留要素分支以构成单独的仅南瓜分支的方法。假设您有一个feature-xyz分支。您可以创建一个feature-xyz-squashed分支,该分支从与feature-xyz分支相同的提交开始,git cherry-pickfeature-xyz到的提交,将feature-xyz-squashed它们压扁,然后合并feature-xyz-squashedmaster。那你不应该合并feature-xyz。有时上述做法是有道理的(例如,您不想包含带有密码的提交),但这是一种解决方法,几乎​​不是最佳实践。
9000
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.