Git 合并不会保留对文件的更改,为什么?

Git 合并不会保留对文件的更改,为什么?,git,merge,Git,Merge,我遇到了这样一种情况,merge会默默地忽略合并分支中的一些更改,我希望(rebase会接受这些更改) 情况如下: * merge slave into master: line not back |\ | * oops, was bad, put the line back (slave branch) | | | * slave branch, also delete the same line * | master branch, delete a line |/ * ini

我遇到了这样一种情况,
merge
会默默地忽略合并分支中的一些更改,我希望(
rebase
会接受这些更改)

情况如下:

* merge slave into master: line not back |\ | * oops, was bad, put the line back (slave branch) | | | * slave branch, also delete the same line * | master branch, delete a line |/ * initial *将从机合并到主机:行未返回 |\ |*糟糕,将线路放回(从分支) | | |*从分支,也删除同一行 *|主分支,删除一行 |/ *首字母 当将
从属
合并到
中时,该行仍然被删除,因此将其放回的提交未被合并。一个再基础会很好

如果不是删除而是修改该行,这将是一个冲突,这对我来说很好。再基础也可以接受回线。但是在没有任何警告的情况下跳过提交。。。我想知道它是为哪些情况设计的

注意:在网上搜索类似的问题发现了很多。。。但所有这些都与合并前删除的整个文件有关。我可以承认原因,即使我更喜欢冲突(而不是失去承诺)。然而,对于文件中的更改,我发现这更令人不安,并且没有发现提及

注意:我在Mercurial上检查了它,结果相同,这不是Git特有的。

原因是(文件级)合并没有看到更改的路径;它可以看到文件的三个版本:
base
我们的
、和
他们的

在分支删除一行然后将其放回的情况下,
它们的
是相同的(至少在相关行上是相同的)。事实上,在
他们的
历史的某个地方,行不会完全相同,合并工具并不知道这一点

所以对于他们的
来说,这条线并不是一个改变了的大块头的一部分;但是对于
我们的
来说是这样的,因此
我们的
中的更改是可以接受的

我同意这不是你想从这次合并中得到的,但我看不到任何合理有效的方法来做得更好。另外,在18年多的编程生涯中,我从未遇到过这种情况——所以“令人不安”可能有点强烈

(我还要指出,您将此描述为“丢失提交”并不准确。提交包含在合并结果中,只是起到了反作用。底线是,自动合并算法永远不会完美;但我们使用的大多数算法都非常好。)

我想,如果您真的想记住分支机构考虑如何处理该行并决定保留该行,您可以对恢复的行进行一些“无意义”的更改。然后,正如您在更改行的情况下所注意到的,它将作为冲突出现

但实际上,您运行单元测试,不是吗?如果这一行足够重要,已经在两个变更行中删除并在其中一个变更行中重新添加,那么如果处理错误,您肯定会有一个失败的测试用例?你知道测试你的合并结果,对吗


重点是,这不是工具的好行为。。。但这是一种罕见的不良行为,无论如何都应该在成熟的开发过程中捕捉并纠正。我不会对它读太多。

这是另一个有趣的例子。我在这里的答案中添加了一个与这个问题相关的链接。谢谢!:-)谢谢我应该想到这一点(答案的第一行解释了一切)。我自然而然地认为,合并的计算方式就像重新基础一样,只是后来组织方式有所不同。我喜欢这样,因为在我看来,这是唯一不丢失数据的方法。好吧,一次应用一个补丁有其利弊(“计算起来像一个重基,只是后来组织得不同”);但如果这是你想要的,只要做一点工作,你就能实现。(编写脚本以:创建临时分支;重新设置该分支的基础;签出“我们的”;开始将“他们的”与
--no commit
;从(重新设置基础的)临时分支更新索引;完成合并;删除临时分支)。但根据定义,您将创建一个“邪恶合并”,这可能会在以后引起麻烦。正如我所说,常规合并的“缺点”很少重要……关于邪恶合并,你是对的。事实上,我认为最好是正常合并,但要注意潜在的问题(使用模拟重基并检测差异?)并报告它。如果从技术上讲这不是冲突,那么它是值得检测的。