我如何“git blame”删除了一行?

时间:2010-12-10 00:05:21

标签: git

git blame非常适合修改和添加的行,但我怎样才能找到最终删除特定先前提交中存在的行的时间。我在想bisect,但我希望有更多的东西。

[在你问之前:在这种情况下,我只是做了一个git log -p并搜索了代码行和(a)一些白痴只是删除了之前的生命线承诺和(b)我是那个白痴]

5 个答案:

答案 0 :(得分:556)

如果你知道该行的内容,这是一个理想的用例:

git log -S <string> path/to/file

显示引入或删除该字符串实例的提交。还有-G<regex>与正则表达式做同样的事情!有关详细信息,请参阅man git-log并搜索-G-S选项或pickaxe(这些功能的友好名称)。

-S联机帮助页的标题中实际上也提到了git-blame选项,在说明部分中,它使用git log -S...给出了一个示例。

答案 1 :(得分:125)

我认为你真正想要的是

git blame --reverse START..END filename

来自the manpage

  

向前走,而不是落后。这不显示出现一行的修订,而是显示一行存在的最后修订版。这需要一系列的修订,如START..END,其中指责路径存在于START中。

使用git blame reverse,您可以找到该行出现的最后一次提交。您仍然需要获得之后的提交。

您可以使用以下命令显示反转的git日志。显示的第一个提交将是该行的最后一次出现,下一次提交将在更改或删除时进行。

git log --reverse --ancestry-path COMMIT^..master

答案 2 :(得分:8)

git blame --reverse 可以让关闭到删除行的位置。但它实际上指向删除行的修订版。它指向最后版本,其中行存在。然后,如果以下版本是一个普通提交,那么你很幸运,你得到了删除修订版。 OTOH,如果以下修订版是合并提交,那么事情就会变得有点疯狂。作为创建 difflame 的努力的一部分,我解决了这个问题,所以如果你已经在你的盒子上安装了python并且你愿意尝试一下,那么不要再等了,让我知道它是怎么回事。

https://github.com/eantoranz/difflame

答案 3 :(得分:6)

只需完成Cascabel答案

git log --full-history -S <string> path/to/file

我遇到了与此处提到的问题相同的问题,但事实证明,由于缺少分支的合并提交,然后又将其合并回去,因此该行丢失了,从而有效地删除了该行。 --full-history标志可防止跳过这些提交。

答案 4 :(得分:0)

对于合并提交中隐藏的更改

合并提交会自动从git-log输出中隐藏其更改。镐和反怪都没有找到变化。因此,我想要的行已添加,后来又删除了,我想找到将其删除的合并。文件git log -p -- path/file的历史记录仅显示该文件已添加。这是我找到它的最佳方法:

git log -p -U9999 -- path/file

搜索更改,然后向后搜索“ ^ commit”-第一个“ ^ commit”是文件最后一行所在的提交。第二个“ ^ commit”消失之后。第二个提交可能是删除它的那个。 -U9999用于显示整个文件内容(每次更改文件后),假设您的文件最大为9999行。

通过蛮力查找任何相关的合并(将每个可能的合并提交与第一个父合并进行比较,以大量提交为准)

git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less

(我尝试过更多地限制修订过滤器,但是我遇到了问题,不建议这样做。我要查找的添加/删除更改是在不同的分支上进行的,这些分支在不同的时间合并到一起,而A ... B确实不包括何时将更改实际合并到主线中。)

显示具有这两次提交的git树(并删除了许多复杂的git-history):

git log --graph --oneline A B ^$(git merge-base A B) (A是上面的第一个提交,B是上面的第二个提交)

显示A历史和B历史减去A和B历史。

备用版本:(似乎比常规的git-history-tree更线性地显示路径-但是我更喜欢常规的git-history-tree):

git log --graph --oneline A...B

3个非2个点-3个点表示“ r1 r2-而不是$(git merge-base --all r1 r2)。这是可从r1(左侧)或r2之一访问的提交集合(右侧),但不能同时来自两者。” -来源:“ man gitrevisions”