GitHub PR壁球导致错误的合并冲突

时间:2019-02-11 17:48:03

标签: git github merge

我想知道这是否是GitHub错误,想查看是否有人发现了此问题。 我的GitHub存储库中有masterdevfeature分支。

过程通常如下所示:

master : A
dev    : A 
feature: A - B - C

然后,我将feature合并到dev中并删除feature分支,但是我不准备保留所有提交历史记录:

master : A
dev    : A - B - C 

当我合并为master时,我会压缩合并使其看起来更干净:

master : A - BC
               \
dev    : A - B - C 

我了解到,BC在这一点上更像是一个单独的提交,但是master的{​​{1}}代码和BC的{​​{1}}代码是相同的。

在以上阶段比较devC时,我注意到一个奇怪的问题;当我尝试再次将master合并到dev中时,我看到很多冲突,反之亦然。

无论将dev合并到master还是dev合并到master中,冲突都不会改变;例如,如果master的代码差异为dev,当我尝试合并dev -> master而不是-a and +b时,我会看到相同的差异。

我们希望继续在master -> dev分支之上构建功能并保留其历史记录,因此将其删除并基于-b and +a创建新分支是不可能的。

我正在使用GitHub压缩和合并,因为其他成员需要批准更改才能合并到dev中。

谁能解释我为什么看到此问题以及如何解决它?

2 个答案:

答案 0 :(得分:1)

此图:

master : A - BC
               \
dev    : A - B - C 

暗示CBC之间存在某种联系。

没有这样的链接,但是在AB之间(具体是从B回到A之间)有一个链接。因此,更准确的绘图是:

A--D   <-- master
 \
  B--C   <-- dev

其中DC具有相同的快照,但没有关联,因此名称为D

这是整个问题的根源:

  

当我尝试再次将dev合并到master时,我看到很多冲突,反之亦然。

就Git而言,devmaster对应的点是提交A。因此,Git必须将从AC的差异,然后再将其应用于master,在Git看来,该差异既没有B也没有C

  

我们希望继续在dev分支之上构建功能并保留其历史记录,因此将其删除并基于master创建新分支是不可能的。

在那种情况下,请停止压扁,因为压扁有效地“杀死”了一个分支:对于B-C提交,您再也不能做任何其他事情。只是做一个真正的合并。在GitHub Web UI中,选择“合并”将执行此操作;在命令行中,使用git merge --no-ff。然后,您将获得一个合并提交(我仍称其为D而不是一个新的完全独立的提交D

A------D   <-- master
 \    /
  B--C   <-- dev

dev上进行更多工作时,您会得到:

A------D   <-- master
 \    /
  B--C--E--F   <-- dev

,您现在可以进行另一次合并。这次不需要--no-ff,尽管它仍然可以正常工作;在GitHub Web UI上也没有任何更改。您将获得一个新的合并提交G

A------D-----G   <-- master
 \    /     /
  B--C--E--F   <-- dev

第二次合并的输入是将提交C作为合并基础,将D提交为--ours,将F提交为--theirs,因此合并将顺利进行。与以前一样,CD中的快照将匹配,而FG中的快照将匹配。

如果您想严格地从master的角度看发生了什么,请使用:

git log --first-parent master

这指示git log仅查看每个合并提交的第一个父级。也就是说,Git首先显示G指向的提交master。然后它将从G移到其第一个父节点D,并显示该提交。然后它将从D移到其第一个父节点A并显示该提交。由于根本没有更早的提交,git log现在停止了,其工作已完成。

(当然,如果在A之前有提交,git log将继续显示它们,但是此处的所有图形在A之前都没有提交。)

答案 1 :(得分:0)

如果您已经将基本分支压缩到 main/master 中,则解决方案是对来自基本分支的所有提交进行交互变基。

假设这是当前状态

master : A - BC
               \
dev    : A - B - C - D

在 dev 上执行 rebase -i HEAD~3,将 C 压缩为 B。然后,D 的父提交将与 master 不同但相似。当您执行 git rebase master 时,您不会遇到合并冲突。

重要
这种做法重写了 git 历史。这意味着您将不得不强制推送更改。永远不要在共享分支上这样做,因为它会破坏其他用户的 git 状态。考虑在 git-scm 中咨询 Rewriting History 以获取更多详细信息。对于单个开发人员正在处理的拉取/合并请求,这种做法是安全的。