How do I "git blame" a deleted line?

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.

(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 just deleted the vital line in the previous commit and (b) I was that idiot.)


Solution 1:

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.

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....

Solution 2:

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.

With git blame reverse, you can find the last commit the line appeared in. You still need to get the commit that comes after.

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 log --reverse --ancestry-path COMMIT^..master

Solution 3:

Just to complete Cascabel's answer:

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

I had the same problem as mentioned here, but it 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.