Richie Thomas
Richie Thomas

Reputation: 3265

Why does "git show HEAD~" show me the 3rd commit in my "git log" list?

I have a regular commit sandwiched in between two merge commits:

commit dc79715411f87e4a4c42c38559ba56ea911a0c01 (HEAD -> master, origin/master, origin/HEAD)
Merge: 097a551 415f5d1
Author: <redacted>
Date:   Tue Aug 14 11:29:54 2018 -0400

    Merge pull request #119 from <redacted>/th-dumb-init

    Use dumb-init instead of phusion

commit 415f5d183dcbf48fb5d27714112308f965438695
Author: <redacted>
Date:   Mon Aug 13 16:13:52 2018 -0400

    Use dumb-init instead of phusion

commit 097a5518087219327ed9f6f3a4499d54a1450cc2
Merge: 9aec35a b63cd1f
Author: <redacted>
Date:   Tue Jul 24 11:01:52 2018 -0400

    Merge pull request #118 from <redacted>/emails_off

    Turn off email alerts for 'orders_populate_every_five_min' Airflow job

When I run git show HEAD, I see the following:

[ sc-airflow ] $ git show HEAD
commit dc79715411f87e4a4c42c38559ba56ea911a0c01 (HEAD -> master, origin/master, origin/HEAD)
Merge: 097a551 415f5d1
Author: <redacted>
Date:   Tue Aug 14 11:29:54 2018 -0400

    Merge pull request #119 from <redacted>/th-dumb-init

    Use dumb-init instead of phusion

This is as I'd expect, since HEAD is currently pointing toward SHA dc79715411f87e4a4c42c38559ba56ea911a0c01.

However, when I type git show HEAD~, I see the following:

[ sc-airflow ] $ git show HEAD~
commit 097a5518087219327ed9f6f3a4499d54a1450cc2
Merge: 9aec35a b63cd1f
Author: <redacted>
Date:   Tue Jul 24 11:01:52 2018 -0400

    Merge pull request #118 from <redacted>/emails_off

    Turn off email alerts for 'orders_populate_every_five_min' Airflow job

This tells me HEAD~ is pointing to SHA 097a5518087219327ed9f6f3a4499d54a1450cc2. However, I would expect HEAD~ to refer to the commit just behind HEAD, or SHA 415f5d183dcbf48fb5d27714112308f965438695. Why is this not the case?

EDIT: Running git log --graph --all --oneline --decorate shows the following:

*   dc79715 (HEAD -> master, origin/master, origin/HEAD) Merge pull request #119 from <redacted>/th-dumb-init
|\  
| * 415f5d1 Use dumb-init instead of phusion
|/  
*   097a551 Merge pull request #118 from <redacted>/emails_off

Upvotes: 0

Views: 448

Answers (1)

torek
torek

Reputation: 488123

Git's git log command shows you commits in some order. OK, so far that's obvious, but here's the tricky part: what order is that?

The first commit that git log shows is a merge commit. That means it has two parents. For convenience, let's call them "Mom" and "Dad" :-) . So, having shown you that commit, now Git will show you Mom first. Or maybe Dad first! Which one will it show? The default is: show the younger (newer) commit.

We know that HEAD~1 is commit 097a5518087219327ed9f6f3a4499d54a1450cc2. That's the first parent, by parent-order—let's call this one Dad since D comes before M. It may not be the first commit, by commit date order, though. If Mom is younger than Dad, git log shows Mom after HEAD. Then Mom has a parent, and if it turns out that Mom's parent is younger than Dad, Git shows you that commit next. Only when it gets to the point where Dad is the next commit to show, does it show Dad.

There are sorting options to git log to tell it which commits to show, and when. Your best bet, though, us to use git log --graph—perhaps with --oneline --decorate as well—so that you can see the commit graph. The ^ and ~ suffix operators are graph-followers, and do not look at the ages of the commits themselves. The log-sorting does look at the ages of the commits by default, but stops doing so when you use --graph.

Upvotes: 4

Related Questions