Git 默默地合并为更新什么应该是冲突
Git silently merges as updates what should be conflicts
简化一下,这就是发生在我们身上的事情:
从 master
上的此文件开始:
class SomeClass {
...
}
创建分支 featureA
off `master.
在 featureA
上,将文件更改为:
class SomeClass {
...
}
extension SomeClass {
// implement feature A
}
- 从 `master.
创建分支 featureB
在 featureB
上,将文件更改为:
class SomeClass {
...
}
class OtherClass {
// implement feature B
}
- 将
featureB
合并到 master
。
- 将
featureA
合并到 master
。
我们期望的是:
class SomeClass {
...
}
extension SomeClass {
// implement feature A
}
class OtherClass {
// implement feature B
}
或者两个加法顺序相反,这样才公平。
实际上,Git 可能会报告冲突:它不了解语义,并且两个 "simultaneous" 更改无法协调。
我们得到的是:
class SomeClass {
...
}
class OtherClass {
// implement feature B
}
没有冲突。也就是说,后来的提交(在另一个提交之前合并)会默默地胜出。
这可以预防吗?怎么样?
注意: 如果我按照上述步骤在干净的回购中尝试此操作,我会在最后一步遇到合并冲突。因此,要么这个问题源于我们在回购协议中所做的其他事情;要么提示表示赞赏,我看不出什么会影响事情。或者问题是 diff 算法被更复杂的代码绊倒了;在生产 Swift 代码中,我们在一侧有两个扩展,在另一侧有一个具有嵌套类型的枚举。
如您所说,当您尝试单独复制它时,这会适当地产生冲突。
此时我的最佳猜测是您的一个分支的开发人员将其他开发人员分支合并到自己的分支中,并通过删除第二个 class 定义解决了冲突。
在您可以证明不是人为错误的错误合并案例中,要考虑的主要事情是 Git 的合并使用 Git 的差异作为输入。如果差异在琐碎的项目上同步,例如碰巧有正确缩进的右括号行,Git 可以将合并结果放在缩进良好的地方,因此 compile,但在语义上不适合,因此不 函数 。
如果您说服 Git 不要同步琐事,则更有可能检测到实际冲突。您可以通过更改合并时使用的 diff 算法来做到这一点。您可以尝试选择 patience
或 histogram
算法,使用 -X patience
或 -X histogram
。有关详细信息的(简短)讨论,请参阅我的周末进展不大的第 3 章(第 65 页)当前的结尾 book。
使用相同的合并尝试进行一些交叉测试:
- 在 Ubuntu 与 Git 2.7.4 和 Meld 3.14.2 上,我看到与
git merge
和 git merge -s patience
的冲突。
在使用 Git 2.11.0 和 Meld 3.16.0 的 Mac 上,我看到 no 与任一合并命令冲突。
相反,
==== BASE ====
}
==== BASE ====
在文件末尾,所以我认为 Meld 在这里没有正确解析差异。
- 在同一 Mac 和同一合并期间,AppCode 2017.3 中的差异查看器显示冲突。
似乎该版本的 Meld 无法解析某些差异。它没有向我显示冲突,所以我在将其标记为已解决之前没有正确修复它。
注意:重现此内容显然需要更多 "matching" 行;我的问题中的小例子没有做到。
简化一下,这就是发生在我们身上的事情:
从
master
上的此文件开始:class SomeClass { ... }
创建分支
featureA
off `master.在
featureA
上,将文件更改为:class SomeClass { ... } extension SomeClass { // implement feature A }
- 从 `master. 创建分支
在
featureB
上,将文件更改为:class SomeClass { ... } class OtherClass { // implement feature B }
- 将
featureB
合并到master
。 - 将
featureA
合并到master
。
featureB
我们期望的是:
class SomeClass {
...
}
extension SomeClass {
// implement feature A
}
class OtherClass {
// implement feature B
}
或者两个加法顺序相反,这样才公平。
实际上,Git 可能会报告冲突:它不了解语义,并且两个 "simultaneous" 更改无法协调。
我们得到的是:
class SomeClass {
...
}
class OtherClass {
// implement feature B
}
没有冲突。也就是说,后来的提交(在另一个提交之前合并)会默默地胜出。
这可以预防吗?怎么样?
注意: 如果我按照上述步骤在干净的回购中尝试此操作,我会在最后一步遇到合并冲突。因此,要么这个问题源于我们在回购协议中所做的其他事情;要么提示表示赞赏,我看不出什么会影响事情。或者问题是 diff 算法被更复杂的代码绊倒了;在生产 Swift 代码中,我们在一侧有两个扩展,在另一侧有一个具有嵌套类型的枚举。
如您所说,当您尝试单独复制它时,这会适当地产生冲突。
此时我的最佳猜测是您的一个分支的开发人员将其他开发人员分支合并到自己的分支中,并通过删除第二个 class 定义解决了冲突。
在您可以证明不是人为错误的错误合并案例中,要考虑的主要事情是 Git 的合并使用 Git 的差异作为输入。如果差异在琐碎的项目上同步,例如碰巧有正确缩进的右括号行,Git 可以将合并结果放在缩进良好的地方,因此 compile,但在语义上不适合,因此不 函数 。
如果您说服 Git 不要同步琐事,则更有可能检测到实际冲突。您可以通过更改合并时使用的 diff 算法来做到这一点。您可以尝试选择 patience
或 histogram
算法,使用 -X patience
或 -X histogram
。有关详细信息的(简短)讨论,请参阅我的周末进展不大的第 3 章(第 65 页)当前的结尾 book。
使用相同的合并尝试进行一些交叉测试:
- 在 Ubuntu 与 Git 2.7.4 和 Meld 3.14.2 上,我看到与
git merge
和git merge -s patience
的冲突。 在使用 Git 2.11.0 和 Meld 3.16.0 的 Mac 上,我看到 no 与任一合并命令冲突。
相反,
==== BASE ==== } ==== BASE ====
在文件末尾,所以我认为 Meld 在这里没有正确解析差异。
- 在同一 Mac 和同一合并期间,AppCode 2017.3 中的差异查看器显示冲突。
似乎该版本的 Meld 无法解析某些差异。它没有向我显示冲突,所以我在将其标记为已解决之前没有正确修复它。
注意:重现此内容显然需要更多 "matching" 行;我的问题中的小例子没有做到。