git blame
非常适合修改和添加的行,但我怎样才能找到最终删除特定先前提交中存在的行的时间。我在想bisect
,但我希望有更多的东西。
[在你问之前:在这种情况下,我只是做了一个git log -p
并搜索了代码行和(a)一些白痴只是删除了之前的生命线承诺和(b)我是那个白痴]
答案 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并且你愿意尝试一下,那么不要再等了,让我知道它是怎么回事。
答案 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”