由`git bisect`或`git log -S --all`找不到由merge提交的更改

时间:2014-06-26 12:50:09

标签: git git-bisect

我修复了一个文件,并将其提交到我的git存储库。

一段时间后,我发现它已经退步了。我想知道修复程序已在哪个提交中被删除,因此我尝试了git bisectgit log --all -S TERM,其中" TERM"是我的修复程序添加的一个字符串,它在项目中没有出现。

我发现git bisect指责了一个不相关的提交,我发现git log --all -S TERM只列出了我添加TERM的提交,并没有列出任何提交删除它,甚至虽然它不再出现在" master"。

的文件中

经过一些手动搜索后,我发现两个分支之间存在合并提交。一个分支有我的修复,一个没有。合并作者选择了没有我修复的分支(奇怪,因为文件中没有冲突)。

我的问题是:

  • 为什么git bisect找不到合并更改?关于此限制,我在联机帮助页中看不到任何内容。是否有不同的方法可以在上述场景中找到错误的合并?
  • 为什么git log --all -S TERM没有列出合并提交?该联机帮助页说它列出了提交"引入或删除"的实例。合并提交不会删除我的字符串吗?是否有不同的方法可以在上述场景中找到错误的合并?
  • 如果git bisectgit log -S在上述方案中无用,那么查找错误合并的有效方法是什么?如果没有这些工具,我会花很长时间来追查有关的变化。

2 个答案:

答案 0 :(得分:3)

  

为什么git log --all -S TERM不列出合并提交?

您必须为其添加-m选项:

git log -m --all -S TERM

为了理解为什么在这种情况下需要特殊选项,让我们首先看一下git log -p的操作,该操作必须包括列出的历史记录中的更改。您可以轻松检查,默认情况下,不显示合并提交更改。原因是更改是两个修订版之间的差异,而对于合并提交,我们有三个(或更多)修订版。 -m option to git log解决了该问题:

  

差异格式

     

...

     

-m

     

此标志使合并提交像常规提交一样显示完整的差异;   对于每个合并父级,单独的日志条目和差异为   生成。唯一的例外是与第一个父项的差异是   在给出--first-parent选项时显示;在这种情况下,输出   表示合并带入当时分支的更改。

然后,假设git log -S就像通过处理git log -p返回的差异一样工作,您应该承认默认情况下,合并提交将从结果中排除。但是,幸运的是,您可以在-S中结合使用-mgit log选项,它可以按预期工作。

答案 1 :(得分:0)

使用git bisect

的解决方案
git bisect start $badCommit $goodCommit
git bisect run bash -c "! git merge-base --is-ancestor $goodCommit HEAD || grep -q $TERM"
bit bisect reset

注意:为简单起见,此解决方案使用git bisect run。您也可以在“交互”模式下使用git bisect。请参阅下面的“说明”部分。

主要思想

这个想法是将bisect算法分析的提交限制在祖先路径中。

CB Baileythis comment中提出了这个想法,尽管我找不到使用git rev-list的方法。

说明

关于git bisect的部分,说明有些棘手。 它基于二等分算法的工作原理。 该算法假设一个好的提交的所有祖先都是好的。 因此,在测试git bisect中的特定提交时,必须将非良好提交的后代也标记为良好。仅使用简单的grep函数时,通常情况并非如此。 您可以使用git merge-base --is-ancestor $goodCommit HEAD(有关How can I tell if one commit is an ancestor of another commit (or vice-versa)?checking if a commit is an ancestor of another的更多信息)来确定这些提交是否是另一次提交的后代