Relative Refs

Typing commit ids gets old fast, and in real git they are 40-character hashes. So git lets you describe a commit by where it sits relative to another one.

~ walks backwards through history: HEAD~1 is one commit back, HEAD~2 is two. It always follows the first parent, so it moves along a single line.

^ picks which parent to follow. On an ordinary commit that is the same thing as ~. But a merge commit has two parents — ^1 is the branch you were on, ^2 is the branch that was merged in — and ^2 is the only way to reach that second line.

These work anywhere a commit is accepted, so branch old main~3 and reset --hard HEAD~1 both do what they look like.

Exercises

  1. Exercise 1. Rather than reading the id off the graph, use a relative ref to check out the commit two steps back from where HEAD is now.
  2. Exercise 2. main points at a merge commit. Check out its second parent — the branch that was merged in — which is the one thing ~ cannot reach.
  3. Exercise 3. Relative refs work when creating branches too. Make a branch called "old" pointing two commits back from main, without moving off main yourself.