Ed Avis
Ed Avis

Reputation: 1482

git blame deleted file, automatically

It is a common question how to run git blame on a file which has earlier been deleted (with git rm). If you just run it with the old filename then it gives the same error as for a file which has never existed:

% git init
% echo 1 >a
% git add a
% git commit -m.
% echo 2 >a
% git add a
% git commit -m.
% git rm a
% git commit -m.
% git blame a
fatal: cannot stat path 'a': No such file or directory
% git blame z
fatal: cannot stat path 'z': No such file or directory

(The responses printed by git to the earlier commands have been omitted to keep things concise.)

A common solution is to look at git log --stat to find the revision in which the file was removed. You can then pass the parent of that revision to git blame:

% git blame 11144~1 -- a
97da6499 (Ed Avis 2016-01-14 11:00:40 +0000 1) 2

This works but it is cumbersome to manually search through the log like this. Is there no way to tell git 'I want to look at whatever files used to be called a in any past revision'? I am hoping for something straightforward like

% git blame --any-file-named a

which would automatically check the whole history of the repository for files with that name.

Upvotes: 3

Views: 2785

Answers (2)

jthill
jthill

Reputation: 60235

You can get the last rev that had the file with git log:

git log --pretty=%H --diff-filter=AM -1 -- path

and git blame does follow changes around:

The origin of lines is automatically followed across whole-file renames (currently there is no option to turn the rename-following off). To follow lines moved from one file to another, or to follow lines that were copied and pasted from another file, etc., see the -C and -M options.

so a dig-it-out-wherever-it-is autoblame alias would be

git config alias.findandblame \
        '!f() { git blame $(git log --pretty=%H --diff-filter=AM -1 -- "$1") -- "$1"; }; f'

Upvotes: 0

categulario
categulario

Reputation: 111

You can always make your own bash function for this:

blame-deleted () {
    git blame $(git rev-list -n 1 HEAD -- $1)~1 -- $1
}

Adding that to your .bashrc will do the trick so you can do:

% blame-deleted a

Upvotes: 4

Related Questions