Reputation: 88708
I've been using Git heavily for about 7 years. A few days ago I found a behavior that surprised me. I found git log
, git blame
and git bisect
to exhibit this weird behavior. A friend let me know about the --full-history
flag to git log
that solved my problem. I want to know, for my own education, whether there is an equivalent fix for git blame
and git bisect
.
Feel free to see the problem for yourself with this repo: https://dl.dropboxusercontent.com/u/1927707/problematic_repo.7z
Here is its log:
$ git log --graph
* commit b7a8d7aa001d06eb7491ab5fb447a8dd3aa421a8
| Author: Ram Rachum <[email protected]>
| Date: Tue Apr 19 17:45:01 2016 +0300
|
| adding more to some-file
|
* commit 0aa833916e908ea93902a6c4c227f9a884a1bcef
|\ Merge: 2413945 3068c7d
| | Author: Ram Rachum <[email protected]>
| | Date: Tue Apr 19 17:44:31 2016 +0300
| |
| | Merge branch 'master' into development
| |
| * commit 3068c7d2548f1798b6840f73b13a649937339f28
| | Author: Ram Rachum <[email protected]>
| | Date: Tue Apr 19 16:02:27 2016 +0300
| |
| | Adding sugar to coffee
| |
* | commit 24139451ab954b1f0a9ef616775a3dba0ac81669
|/ Author: Ram Rachum <[email protected]>
| Date: Tue Apr 19 16:01:28 2016 +0300
|
| Creating some-file
|
* commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661
Author: Ram Rachum <[email protected]>
Date: Tue Apr 19 16:00:47 2016 +0300
Create coffee
In the very first commit, the file coffee
was added. In the commit 3068c7d
, I added a line "sugar" to the coffee
file. But then I merged this branch into the development
branch, and in that merge, a mistake was made and the "sugar" line was removed, leaving coffee
empty. Then another commit b7a8d7a
, making an unrelated change, was added for good measure.
Now I'm looking at my coffee, and finding there's no sugar in it. I distinctly remember adding sugar to my coffee. I run git log coffee
, and get this output:
$ git log coffee
commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661
Author: Ram Rachum <[email protected]>
Date: Tue Apr 19 16:00:47 2016 +0300
Create coffee
That's it. git log
is showing neither my original commit that added the sugar, nor the merge that removed it. Two very relevant commits that are missing.
I was frustrated for about an hour by this problem, because it happened in a huge enterprise repo, where commits are much harder to find manually.
I also tried using git bisect
and git blame
to pin down the two commits, but both of these tools ignored the two commits. git bisect
pointed me to the wrong commit after I finished doing all the git bisect bad
and git bisect good
actions.
Then, as I said in the beginning, a friend pointed me towards the --full-history
flag:
$ git log --full-history --graph coffee
* commit 0aa833916e908ea93902a6c4c227f9a884a1bcef
|\ Merge: cf02fbb 3068c7d
| | Author: Ram Rachum <[email protected]>
| | Date: Tue Apr 19 17:44:31 2016 +0300
| |
| | Merge branch 'master' into development
| |
| * commit 3068c7d2548f1798b6840f73b13a649937339f28
|/ Author: Ram Rachum <[email protected]>
| Date: Tue Apr 19 16:02:27 2016 +0300
|
| Adding sugar to coffee
|
* commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661
Author: Ram Rachum <[email protected]>
Date: Tue Apr 19 16:00:47 2016 +0300
Create coffee
This makes me happy because it shows the two relevant commits, the one adding sugar and the merge that removed it. So my problem is solved. But I really wish I could know how to make git bisect
and git blame
behave as well. Does anyone happen to know?
Upvotes: 8
Views: 395
Reputation: 489758
Interesting. Since the line isn't there, git blame
starts out quite unhelpful. As the documentation for git blame
notes:
The report does not tell you anything about lines which have been deleted or replaced; you need to use a tool such as git diff or the "pickaxe" interface briefly mentioned in the following paragraph.
In this case we might run git log -SSugar
to find where it went in:
$ git log --pretty=oneline -SSugar
3068c7d2548f1798b6840f73b13a649937339f28 Adding sugar to coffee
but git blame
won't immediately help us find where it went out. (And as you have just discovered, if we want to find that line when mentioning files, we may need --full-history
, since adding path(s) to limit the commits git log
will consider, also causes history simplification by pruning each commit's tree to contain just the mentioned files and then using that TREESAME
code.)
Starting from the known-good rev, we can now try --reverse
[edit: I noticed 3068c7d2548f1798b6840f73b13a649937339f28
== master
and actually used master
here, probably should have used the SHA-1 directly]:
$ git blame --reverse master..HEAD coffee
^3068c7d (Ram Rachum 2016-04-19 16:02:27 +0300 1) Sugar
This seems to imply that 3068c7d
is the last rev in which the line exists, so it must be deleted in some or all of the children along this particular path, which is true:
$ git log --oneline --graph --decorate --all
* b7a8d7a (HEAD -> development) adding more to some-file
* 0aa8339 Merge branch 'master' into development
|\
| * 3068c7d (master) Adding sugar to coffee
* | 2413945 Creating some-file
|/
* cf02fbb Create coffee
There is only one commit that is a child of 3068c7d
here, namely 0aa8339
, so:
$ git show -m 0aa8339
commit 0aa833916e908ea93902a6c4c227f9a884a1bcef (from 3068c7d2548f1798b6840f73b1
Merge: 2413945 3068c7d
Author: Ram Rachum <[email protected]>
Date: Tue Apr 19 17:44:31 2016 +0300
Merge branch 'master' into development
diff --git a/coffee b/coffee
index 4d0f160..e69de29 100644
--- a/coffee
+++ b/coffee
@@ -1 +0,0 @@
-Sugar
diff --git a/some-file b/some-file
new file mode 100644
index 0000000..e69de29
(we need -m
to get git to compare the merge against both parents). And that does find it, in a slightly roundabout way.
(Meanwhile, there seems to be no cure for the bisect issue. Well, other than "avoid evil merges"...)
Upvotes: 1