13

我对文件进行了修复,并将其提交到我的git存储库。

过了一段时间,我发现它已经退步了。我想知道修复程序是在哪个提交中被删除的,所以我尝试了git bisectand git 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如果没有这些工具,我似乎需要很长时间才能追踪有问题的变化。
4

2 回答 2

5

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

您必须向-m其中添加选项:

git log -m --all -S TERM

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

差异格式

...

-m

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

然后,假设git log -S通过处理返回的差异来工作,git log -p您应该承认默认情况下合并提交将被排除在结果之外。但是,幸运的是,您可以将-S-m选项结合起来git log,它可以按预期工作。

于 2018-08-03T20:23:49.930 回答
2

解决方案使用git bisect

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

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

大意

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

CB Bailey此评论中提出了这个想法,尽管我没有找到使用git rev-list.

解释

关于 的部分git bisect,解释有点棘手。它基于 bisect 算法的工作原理。该算法假设一个好的提交的所有祖先都是好的。因此,在测试特定提交时git bisect,您必须将不是好提交的后代的提交也标记为好。仅使用简单的 grep 函数时通常不会出现这种情况。您可以使用git merge-base --is-ancestor $goodCommit HEAD(有关如何判断一个提交是否是另一个提交的祖先(反之亦然)的更多详细信息?检查一个提交是否是另一个提交的祖先)来判断提交是否是另一个提交的后代

于 2018-10-10T19:11:33.940 回答