10

In a Udacity lesson covering relative commit references, it says:

^ indicates the parent commit, ~ indicates the first parent commit

The main difference between the ^ and the ~ is when a commit is created from a merge. A merge commit has two parents. With a merge commit, the ^ reference is used to indicate the first parent of the commit while ^2 indicates the second parent. The first parent is the branch you were on when you ran git merge while the second parent is the branch that was merged in.

According to the lesson, based on the following output of git log --graph --oneline, the commit with SHA f69811c is HEAD~4^2 relative to the (topmost, with the head pointer) commit 9ec05ca.

So HEAD~4 on its own means the first parent, while ^2 means it's also the second parent? Don't these things contradict each other? Any clarification appreciated.

graph

nCardot
  • 5,992
  • 6
  • 47
  • 83
  • 2
    https://stackoverflow.com/q/2221658/1030675 – choroba May 20 '18 at 19:43
  • 2
    Instead of reading third-party tutorials, I recommend [the Git docs themselves](https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection). `~n` says chase a first-parent link that many times, default 1, `^n` says chase the nth-parent link, default 1. – jthill May 20 '18 at 23:15

2 Answers2

17

X~n means: The nth ancestor of X.

X^ means: The parent of X. This is equivalent to X~1.

If X has more than one parent, one needs to distinguish between them when using the ^ notation. So X^1 would be the first parent, X^2 would be the second parent, and so on. X^ is equivalent to X^1 (and also equivalent to X~1).

In your example, starting from commit 9ec05ca, which is HEAD:

  • db7e87a is HEAD~1 (or alternatively HEAD^).
  • 796ddb0 is HEAD~2 (or alternatively HEAD^^).
  • 1a56a81 is HEAD~4 (or alternatively HEAD^^^^, but nobody would use that).
  • e014d91, being the first parent of 1a56a81, is HEAD~5, or HEAD~4^, or HEAD~4^1.
  • f69811c, being the second parent of 1a56a81, is HEAD~4^2.

Reference

https://git-scm.com/docs/gitrevisions

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • Thank you, I'm not grasping your last two points. Is Udacity wrong in saying ~ means first parent? – nCardot May 20 '18 at 21:38
  • 1
    It's not wrong though a bit confusing. `~n` means "select the nth generation ancestor, always following the first parents", while `^n` means "among the previous generation, select the nth parent." – jingx May 20 '18 at 22:01
  • Since e6c65a6 is on the branch that was merged into master, is it also a second parent of 1a56a81 (merge commit), in addition to f69811c? – nCardot May 21 '18 at 02:18
  • 1
    @NatalieCardot No, `e6c65a6` is not a parent of `1a5681` at all, it is one of its grandparents (because it is the parent of `f69811c`). – mkrieger1 May 21 '18 at 20:52
  • Bonus question: What is the other grandparent of `1a5681`? – mkrieger1 May 21 '18 at 20:53
  • 1a5681's other grandparent is 209752a (plus, its great grandparent is 3772ab1). I think I finally understand :) – nCardot May 22 '18 at 20:51
1

It's not totally wrong, but it's a bit too short: since the "~" operator is performing a depth search (nth ancestor, which actually corresponds to the nth last commit on a single branch), its argument can't specify a parent if they are many of them. It hence assumes it should always follow the first one of them. This correlates with your other question, where we were discussing about parent order.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Obsidian
  • 3,719
  • 8
  • 17
  • 30