10

我们有一个版本,有问题的提交 (daf7110) 在合并回 master 的历史记录中。此时(85a13270),master有daf7110添加的代码行。

当我们的一位开发人员将 master 合并到他的分支(dev-branch)中时,代码行就消失了。它们从未存在于合并的开发者一方的历史中。我通过以下方式验证了这一点:

git checkout c513d2 # <--last commit on dev-branch before the merge
git log -S string_that_was_added -- lib/File/It/Was/In.pm

所以:

  1. 在合并之前,该代码从未存在于 dev-branch 上。
  2. 它在 master 上,从“git merge-base c513d2 85a13270”开始添加

我怎样才能更详细地了解为什么 Git 的合并逻辑决定代码不应该在合并后继续存在?还是有其他原因我的提交无法在合并中幸存下来?

4

2 回答 2

13

我不知道为什么会发生这种情况,但我可以提供一些调试技巧。

首先,我会确保您没有任何奇怪的设置。在没有 Git 配置的帐户中对具有这两个分支的存储库进行全新克隆。尝试进行合并。它仍然发生吗?如果没有,请检查您的设置,看看是否有任何异常;特别是,我会怀疑任何rerere设置。另外,尝试进行合并--no-rerere-autoupdate以查看它是否仍然丢弃有问题的行。

之后,我将首先打开合并的最大详细程度,然后尝试再次进行合并:

GIT_MERGE_VERBOSITY=5 git merge -v master

这将为您提供有关合并过程做出的决策的更多信息。

如果这最终没有告诉您任何有用的信息,您还可以尝试查看它是否发生在不同的合并策略或默认的递归合并策略的不同选项中。尝试git merge -s resolve尝试更简单但更愚蠢的合并策略。你还有问题吗?如何为递归策略尝试不同的选项,例如git merge -s recursive -X patience?在打开额外冗长的情况下执行最后一个,看看是否会做出与默认合并策略不同的决定。

如果这不起作用,那么是时候尝试手动将其减少到最小的测试用例了。首先,我会尝试将自己限制在有问题的文件中。确保您在一次性存储库中工作,并使用git filter-branch删除所有文件,但有问题的文件中缺少这些行。当您这样做并再次尝试合并时,您会得到相同的结果吗?如果不是,那么这些行可能会消失,因为 Git 感到困惑并认为它们移动到了另一个文件,而实际上并没有。

如果您仍然可以仅使用一个文件重现问题,那么是时候开始回溯每个分支的修订历史,进行合并,直到问题消失。例如,从开发分支开始,大约跳到一半,再次尝试合并,看看来自 master 的行是否仍然消失。如果他们这样做了,请尝试跳得更远。如果没有,请沿着开发分支向前跳转,然后重试。一旦您找到了在开发方面引入问题的提交,请在 master 上尝试相同的操作,将您正在合并的提交移回,直到问题消失。

既然您已经尽可能地返回,请尝试重新创建该点之前的历史简化版本。创建一个新的 Git 存储库,签入这两个提交的合并基础。然后在单独的分支中签入您在上面跟踪到的两个提交。您可以毫无问题地合并那些,还是取​​决于两者之间合并拓扑的某些方面?如果是,请尝试重新创建完整的合并拓扑;仅创建执行历史记录中所有合并所需的提交。这可以重现您的问题吗?

在这一点上,您应该拥有最简单的历史来重现问题,只需一个文件来演示它(或者当您无法进一步减少它并重现问题时会发现一些有趣的东西)。我建议要么公开发布此存储库,以便我们可以查看它,如果该文件中没有任何敏感内容,或者如果有,尝试进一步减少它,编辑每个提交以删除所有内容,但是相关线路。您还应该能够用占位符值替换每个相关行,从而为您留下一个不包含任何实际代码的最小测试用例。

以上所有工作都是大量的工作,但希望您在完成所有工作之前会发现一些有趣的东西,或者可以跳过并生成最小的测试用例而无需完成所有中间步骤。一旦你有一个更简单的测试用例,或者上述步骤之一的结果,发布它们,我们可以仔细看看。

于 2012-04-12T04:12:37.990 回答
4

我遇到了类似的问题。看起来这是因为有问题的代码行首先由提交引入,然后被还原删除。该分支已合并到主分支。

然后在开发分支上重新引入了该行,但在将开发分支合并到主分支时,它被系统地剥离了。我假设 Git 会以某种方式跟踪还原,并假设不需要此行并应将其删除。

于 2015-04-08T16:33:10.600 回答