我如何“git blame”删除的行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4404444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I "git blame" a deleted line?
提问by Malvolio
git blame
is great for modified and added lines, but how can I find when a line that existed in a specific previous commit was eventually deleted. I'm thinking bisect
, but I was hoping for something handier.
git blame
非常适合修改和添加的行,但是我如何找到特定先前提交中存在的行最终被删除的时间。我在想bisect
,但我希望有更方便的东西。
(Before you ask: in this case, I just did a git log -p
and searched through for the code line and (a) some idiot had justdeleted the vital line in the previous commit and (b) I was that idiot.)
(在你问之前:在这种情况下,我只是做了一个git log -p
并搜索了代码行,并且(a)某个白痴刚刚删除了上一次提交中的重要行,(b)我就是那个白痴。)
回答by Cascabel
If you know the contents of the line, this is an ideal use case for:
如果您知道该行的内容,这是一个理想的用例:
git log -S <string> path/to/file
which shows you commits which introduce or remove an instance of that string. There's also the -G<regex>
which does the same thing with regular expressions! See man git-log
and search for the -G
and -S
options, or pickaxe (the friendly name for these features) for more information.
它显示了引入或删除该字符串实例的提交。还有-G<regex>
用正则表达式做同样的事情!查看man git-log
和搜索-G
和-S
选项,或镐(这些功能的友好名称)以获取更多信息。
The -S
option is actually mentioned in the header of the git-blame
manpage too, in the description section, where it gives an example using git log -S...
.
该-S
选项实际上也在手册git-blame
页的标题中提到,在描述部分,它给出了一个使用git log -S...
.
回答by Chronial
I think what you really want is
我想你真正想要的是
git blame --reverse START..END filename
From the manpage:
从联机帮助页:
Walk history forward instead of backward. Instead of showing the revision in which a line appeared, this shows the last revision in which a line has existed. This requires a range of revisions like START..END where the path to blame exists in START.
向前而不是向后走历史。这不是显示出现行的修订版,而是显示存在行的最后一个修订版。这需要一系列修订,例如 START..END,其中 START 中存在归咎路径。
With git blame reverse
, you can find the last commit the line appeared in. You still need to get the commit that comes after.
使用git blame reverse
,您可以找到该行出现的最后一次提交。您仍然需要获取之后的提交。
You can use the following command to show a reversed git log. The first commit shown will be the last time that line appears, and the next commit will be when it is changed or removed.
您可以使用以下命令来显示反向的 git 日志。显示的第一次提交将是该行最后一次出现,而下一次提交将是该行被更改或删除的时间。
git log --reverse --ancestry-path COMMIT^..master
回答by estani
Just to complete Cascabel's answer:
只是为了完成卡斯卡贝尔的回答:
git log --full-history -S <string> path/to/file
I had the same problem as mentioned here, butit turned out that the line was missing, because a merge commit from a branch got reverted and then merged back into it, effectively removing the line in question. The --full-history
flag prevents skipping those commits.
我遇到了与此处提到的相同的问题,但结果是该行丢失了,因为来自分支的合并提交被还原然后合并回它,从而有效地删除了有问题的行。该--full-history
标志可防止跳过这些提交。
回答by eftshift0
git blame --reversecan get you closeto where the line is deleted. But it actually doesn'tpoint to the revision where the line is deleted. It points to the lastrevision where the line was present. Then if the following revisionis a plain commit, you are lucky and you got the deleting revision. OTOH, if the following revision is a merge commit, then things can get a little wild.
git blame --reverse可以让您接近删除行的位置。但它实际上并不指向删除该行的修订版。它指向的最后一个修订版本,其中线是目前。那么如果下面的修订是一个普通的提交,你很幸运,你得到了删除修订。OTOH,如果以下修订是合并提交,那么事情可能会变得有点疯狂。
As part of the effort to create difflameI tackled this very problem so if you already have Python installed on your box and you are willing to give it a try, then don't wait any longer and let me know how it goes.
作为创建difflame的努力的一部分,我解决了这个问题,所以如果你已经在你的机器上安装了 Python 并且你愿意尝试一下,那么不要再等了,让我知道它是怎么回事。
回答by Curtis Yallop
For changes hidden in merge commits
对于隐藏在合并提交中的更改
Merge commits automatically have their changes hidden from the Git log output. Both pickaxeand reverse-blamedid not find the change. So the line I wanted had been added and later removed and I wanted to find the merge which removed it. The file git log -p -- path/file
history only showed it being added. Here is the best way I found to find it:
合并提交会自动将其更改隐藏在 Git 日志输出中。无论镐头和反指责没有发现变化。所以我想要的那行已经被添加了,后来又被删除了,我想找到删除它的合并。文件git log -p -- path/file
历史记录只显示它被添加。这是我找到的最佳方法:
git log -p -U9999 -- path/file
git log -p -U9999 -- path/file
Search for the change, then search backwards for "^commit" - the first "^commit" is the commit where the file last had that line. The second "^commit" is after it disappeared. The second commit might be the one that removed it. The -U9999
is meant to show the entire file contents (after each time the file was changed), assuming your files are all max 9999 lines.
搜索更改,然后向后搜索“^commit” - 第一个“^commit”是文件最后具有该行的提交。第二个“^提交”是在它消失之后。第二次提交可能是删除它的一次提交。本-U9999
是为了显示整个文件内容(每个文件被更改时间后),假设你的文件都是最高9999线。
Finds any related merges via brute force(diff each possible merge commit with its first parent, run against tons of commits)
通过蛮力查找任何相关的合并(将每个可能的合并提交与其第一个父项进行区分,针对大量提交运行)
git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less
git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less
(I tried restricting the revision filter more, but I ran into problems and don't recommend this. The add/removal changes I was looking for were on different branches which were merged in at different times and A...B did not include when the changes actually got merged into the mainline.)
(我尝试更多地限制修订过滤器,但我遇到了问题,不建议这样做。我正在寻找的添加/删除更改位于不同的分支上,这些分支在不同的时间合并,而 A...B 不包括当更改实际合并到主线时。)
Show a Git tree with these two commits(and a lot of the complex Git history removed):
显示带有这两个提交的 Git 树(并删除了许多复杂的 Git 历史记录):
git log --graph --oneline A B ^$(git merge-base A B)
(A is the first commit above, B is the second commit above)
git log --graph --oneline A B ^$(git merge-base A B)
(A 是上面的第一次提交,B 是上面的第二次提交)
Show history of A and history of B minus history of both A and B.
显示 A 的历史和 B 的历史减去 A 和 B 的历史。
Alternate version (seems to show the path more linearly rather than the regular Git history tree - however I prefer the regular git history tree):
替代版本(似乎更线性地显示路径而不是常规的 Git 历史树 - 但我更喜欢常规的 git 历史树):
git log --graph --oneline A...B
Three, not two dots - three dots means "r1 r2 --not $(git merge-base --all r1 r2). It is the set of commits that are reachable from either one of r1 (left side) or r2 (right side), but not from both." - source: "man gitrevisions"
三个,而不是两个点——三个点的意思是“r1 r2 --not $(git merge-base --all r1 r2)。它是可以从 r1(左侧)或 r2(右侧)之一访问的提交集方面),但不是来自两者。” - 来源:“man gitrevisions”