首页 > 解决方案 > 由于不相关的“变化”而压制先前的冲突

问题描述

有时当我将后一个提交压缩到一个早期提交时,我会遇到意想不到的冲突。

设置

我在这里有一个示例存储库,其结构如下。

git log --all --decorate --oneline --graph
* 3aa1300 (HEAD -> master, origin/master) Refactor func(x)
* 6b8940e Add func2
* 6ead589 Add import math
* dc55678 Add func
* 9dfc660 add file.py
* c5fd61b Initial commit

为了便于使用,我将它们称为字母提交:

D 3aa1300 Refactor func(x)
C 6b8940e Add func2
B 6ead589 Add import math
A dc55678 Add func
AA 9dfc660 add file.py
AAA c5fd61b Initial commit

提交名称是不言自明的,但这里有一个缩写git log -p

commit D: Refactor func(x)

 import math

-def func(x):
-    return(x)
+def func(y):
+    return(y)

 def func2(y):
     return(y)

commit C: Add func2

 def func(x):
     return(x)
+
+def func2(y):
+    return(y)

commit B: Add import math

+import math
+
 def func(x):
     return(x)

commit A: Add func

+def func(x):
+    return(x)

commit AA: add file.py
[Add the file. Only here to have commit to rebase from]

问题

我正在清理分支,所以我想D挤进A. 所以我git rebase -i HEAD~4使用以下命令执行:

pick A Add func
squash D Refactor func(x)                                                                                                                                                                                                               
pick B Add import math
pick C Add func2

这样做会让我在以下方面产生冲突file.py

<<<<<<< HEAD                                                                                                                                                                                                                                  
def func(x):                                                                                                                                                                                                                                  
    return(x)
=======
import math

def func(y):
    return(y)

def func2(y):
    return(y)
>>>>>>> 3aa1300... Refactor func(x)

问题

为什么壁球不只是“发生”?为什么壁球会将所有其他不相关的变化引入冲突?

我假设提交基本上只是存储了它执行的“差异补丁”。所以D只会带来

-def func(x):
-    return(x)
+def func(y):
+    return(y)

没有别的了。

隐含问题:

假设我只是没有做正确的事情,我应该如何进行“修复”D并将它们压缩到A

标签: git

解决方案


我假设存储的提交基本上只是存储了它执行的“差异补丁”。

情况并非如此:每次提交都完整地保存了所有文件的完整快照。当挑选一个提交来复制它时——并且 rebase 会这样做,甚至(或特别是?)通过squash操作——这些快照通过使用的修改后的三向合并过程变成git cherry-pick差异。因此,将它们视为差异主要是可行的。不过,这主要是在这里成为问题的部分。

你实际上是在做正确的事。Git 被触发了,因为有问题的差异是从提交C到提交A,然后提交C到提交D,即使提交C尚未被复制。如果您设置merge.conflictStylediff3,Git 将在发生冲突的地方包含来自 merge-base commit 的内容C。这会让你看到 Git 将 commit A——或者更确切地说,C-to A-change-set - 视为删除 func2,同时C-to D-change-setfunc1在重叠或邻接的行中修改(在这种情况下,我认为“邻接") 此删除。


推荐阅读