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.
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.
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.
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^1means the first parent' - '
HEAD^2means the second parent' - '
HEAD~1means the first parent' - '
HEAD~2means 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.
Use ~ when you simply want to move back through recent history on the current branch.
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' - '
~nmeans walk first parentntimes'
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.
The graph view makes merge parents visible, which is exactly where confusion about ^ and ~ usually starts.
Common Pitfalls
- Assuming
HEAD^andHEAD~1are always different, even though they are the same on ordinary commits. - Assuming
HEAD^2means “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~nfollows the first parentntimes.' - On non-merge commits,
HEAD^andHEAD~1resolve to the same commit. - On merge commits,
HEAD^2can point somewhereHEAD~cannot name directly. - Use
^for parent selection and~for first-parent history traversal.

