Git
Version Control
Programming
Software Development
Coding Practices

What's the difference between HEAD^ and HEAD~ in Git?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

HEAD^ and HEAD~ are both ways to refer to ancestors of the current commit, but they are not interchangeable in every situation. The short version is that ^ selects a specific parent of a commit, while ~ walks backward through the first-parent chain a given number of times.

Start with a Simple Non-Merge Commit

On an ordinary commit with exactly one parent, these notations look the same.

bash
git rev-parse HEAD^
git rev-parse HEAD~1

Both commands resolve to the immediate parent of HEAD when HEAD is not a merge commit. That is why the two forms often seem equivalent at first.

^ Means “Parent Number”

The caret form chooses a parent directly. HEAD^ is the same as HEAD^1, which means the first parent.

If the commit is a merge commit, you can choose a different parent explicitly.

bash
git show HEAD^1
git show HEAD^2

HEAD^2 means the second parent of the current merge commit. That is something HEAD~ cannot express directly.

~ Means “Walk First Parent N Times”

The tilde form follows the first parent repeatedly.

bash
git show HEAD~1
git show HEAD~2
git show HEAD~3

HEAD~3 means “start at HEAD, then follow the first parent three times.” It is shorthand for:

  • 'HEAD^1^1^1'

That makes ~ very convenient for linear history traversal, interactive rebase ranges, and quick navigation on the main branch.

The Difference Matters on Merge Commits

Imagine HEAD is a merge commit with two parents. Then:

  • 'HEAD^1 means the first parent'
  • 'HEAD^2 means the second parent'
  • 'HEAD~1 means the first parent'
  • 'HEAD~2 means the first parent of the first parent'

So HEAD^2 and HEAD~2 are completely different references.

That is the real conceptual difference: ^ chooses among parents at one step, while ~ keeps walking down the first-parent path.

Use Cases for Each Form

Use ^ when you care about merge structure, especially when inspecting or diffing a specific parent of a merge commit.

bash
git diff HEAD^1 HEAD
git diff HEAD^2 HEAD

Use ~ when you simply want to move back through recent history on the current branch.

bash
git rebase -i HEAD~4

That command is common because it means “rewrite the last four commits along the first-parent line.”

Read the Notation as Navigation, Not Magic

These operators look cryptic only until you read them mechanically.

  • '^ means select parent number'
  • '~n means walk first parent n times'

Once you read them that way, expressions such as HEAD~2^2 become understandable instead of memorized symbols.

Use git log --graph When in Doubt

If a reference expression resolves differently than expected, inspect the commit graph.

bash
git log --oneline --graph --decorate -n 12

The graph view makes merge parents visible, which is exactly where confusion about ^ and ~ usually starts.

Common Pitfalls

  • Assuming HEAD^ and HEAD~1 are always different, even though they are the same on ordinary commits.
  • Assuming HEAD^2 means “two commits back” instead of “second parent of the current commit.”
  • Using ~ when the real need is to inspect a specific merge parent.
  • Forgetting that ~ always follows only the first-parent chain.
  • Trying to reason about complex references without looking at the actual commit graph.

Summary

  • 'HEAD^ selects a parent, usually the first one unless you specify another.'
  • 'HEAD~n follows the first parent n times.'
  • On non-merge commits, HEAD^ and HEAD~1 resolve to the same commit.
  • On merge commits, HEAD^2 can point somewhere HEAD~ cannot name directly.
  • Use ^ for parent selection and ~ for first-parent history traversal.

Course illustration
Course illustration

All Rights Reserved.