我如何"git blame"删除了一行?

Mal*_*lio 473 git

git blame非常适合修改和添加的行,但是如何最终删除特定先前提交中存在的行.我在想,bisect但我希望有更方便的东西.

[在你问之前:在这种情况下,我只是做了一个git log -p并搜索了代码行和(a)一些白痴刚刚删除了前一次提交中的重要行和(b)我是那个白痴]

Cas*_*bel 598

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

git log -S <string> path/to/file
Run Code Online (Sandbox Code Playgroud)

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

-S选项实际上也在手册git-blame页的标题中提到,在描述部分中,它给出了一个使用示例git log -S....

  • 使用Git 1年后,我仍然惊讶地看到Git*总是*在某个地方有一个命令/选项来解决我几乎所有的使用场景.感谢分享这个,这正是我现在所需要的! (32认同)
  • 这个方法以前对我有用,但刚才我看到了一个没有找到删除行的提交的情况.事实证明,在合并提交中删除了有问题的行 - 这会解释失败吗?(`git blame --reverse`方法虽然找到了它.) (21认同)
  • @antinome要显示合并提交,请另外使用`-c`选项. (7认同)
  • 我在联机帮助页上的“-s”上执行了 ctrl+f 操作,但什么也没找到。你在页面的什么地方看到的??我正在使用 git 1.8.5.2 (2认同)
  • 请注意,您不必针对单个文件运行该命令。`git log -S ... path/to/directory` 工作正常。 (2认同)

Chr*_*ial 132

我想你真正想要的是

git blame --reverse START..END filename
Run Code Online (Sandbox Code Playgroud)

联机帮助页:

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

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

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

git log --reverse --ancestry-path COMMIT^..master
Run Code Online (Sandbox Code Playgroud)

  • 如果从分支中有多个合并,其中行被添加到缺少行的分支中(或者从START到END的行中有多个路径的任何其他情况),`git blame --reverse`将显示在合并之前的修订是按时间顺序排在最后的,而不是在初始合并之前的修订,其中决定不采取该行.是否有某种方法可以找到最早的修订版,其中该行已停止存在而不是最近的版本? (14认同)
  • @rakslice,因为你可以使用blame --reverse --first-parent,它稍好一些. (2认同)

est*_*ani 14

刚刚完成Cascabel的回答

git log --full-history -S <string> path/to/file
Run Code Online (Sandbox Code Playgroud)

我这里提到了同样的问题,但事实证明,在一行丢失,因为合并提交一个分支得到了恢复,然后合并到它,有效去除有问题的线路.该--full-history标志可防止跳过这些提交.


eft*_*ft0 8

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

https://github.com/eantoranz/difflame


Cur*_*lop 7

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

合并提交会自动将其更改隐藏在 Git 日志输出中。反向责怪都没有发现变化。因此,我想要的行已被添加,后来被删除,我想找到删除它的合并。文件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 历史记录):

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

显示 A 的历史记录和 B 的历史记录减去 A 和 B 的历史记录。

替代版本(似乎比常规 Git 历史树更线性地显示路径 - 但我更喜欢常规 git 历史树):

git log --graph --oneline A...B
Run Code Online (Sandbox Code Playgroud)

三个,而不是两个点 - 三个点表示“r1 r2 --not $(git merge-base --all r1 r2)。它是可从 r1(左侧)或 r2(右侧)之一访问的提交集侧),但不是来自双方。” - 来源:“man gitrevisions”