开发者

Who deleted my change in git?

Here was my problem for the last 30 minutes: I had a couple of changes that disappeared in one of my files, and I don't know when that happened. And I want to know who did that!

I started looking for the revisions having my files:

git grep <searched_string> $(git rev-list --al开发者_如何学Cl) -- <file>

is the path to the file or a wildcard like *.gsp

I got a bunch of revisions, I look at the last one, and try to get it's children (thinking the first child should be the first revision where my changes disappeared)

git rev-list --children <revision_id>

is the 40 chars from the beginning of the last line of the previous command

Getting close! I am looking at the beginning of the output, and take the first child and then run

git log <revision_id_s_first_child> --stat

Then I look at the output and find my file and who did the change! (it turned out, I was to blame...)

Is there anyway to do that faster (git blame would not show what has been deleted) ?


git blame has a --reverse option that takes a range of commits and shows you the last commit where a line existed before it was deleted. So, you find a commit you know the lines were there, let's say abcdef01 for example, and to show the last commit before the delete, do:

git blame --reverse abcdef01..HEAD -- <file>


If you know some substring that would be in the line that was removed, then you can use the -G option to git log to find commits that introduced a change that added or removed lines containing that substring. e.g. if you knew that the word "pandemic" was in the line that disappeared, you can do:

git log -Gpandemic -p

(The parameter to -G can be a regular expression.) This option was added rather recently to git - if it doesn't work, try -S instead, which has slightly different semantics, but should have a similar effect.


Note that since Git 2.11 (Q4 2016), you won't have to specify ..HEAD if you want to look at commits between a specific one and the current one.

So Karl Bielefeldt's answer would then be:

 git blame --reverse abcdef01 -- <file>

See commit d993ce1 (14 Jun 2016) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 1172e16, 10 Oct 2016)

blame: dwim "blame --reverse OLD" as "blame --reverse OLD.."

It is a common mistake to say "git blame --reverse OLD path", expecting that the command line is dwimmed as if asking how lines in path in an old revision OLD have survived up to the current commit.

Instead of always requiring both ends of a range, we could DWIM "OLD", which could be a misspelt "OLD..", to be a range that ends at the current commit.

git blame --reverse now include:

--reverse <rev>..<rev>:

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 revision like START..END where the path to blame exists in START.
git blame --reverse START is taken as git blame --reverse START..HEAD for convenience.

(Note of the note: "dwim" is an acronym for "Do What I Mean" (not what I say))


git blame --reverse can get you close to where the line is deleted. But it actually doesn't point to the revision where the line is deleted. It points to the last revision where the line was present. Then if the following revision is 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. As part of the effort to create difflame I 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.

https://github.com/eantoranz/difflame

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜