Git HEAD, Detached HEAD and Revision Syntax

Understand Git HEAD, detached HEAD, parent notation and commit ranges through a local lab, recovery exercises and practical reference questions.

Lesson 22 of 30Intermediate10 min read

HEAD appears in Git commands so often that it can look like a special branch name. It is better understood as the reference identifying your current checkout. Usually it points through the branch you are working on. A detached checkout instead names a commit directly. Neither state is mysterious once you distinguish a commit from a movable branch reference. This guide explains that difference, parent notation and command-specific range behavior. You will inspect an older snapshot without changing main, then give that checkout a branch name before continuing work.

Distinguish objects from their names

A commit records a snapshot and links to its parent commits. Its object identity does not move when you rename or advance a branch. A branch reference names a commit and normally moves when you make a new commit on that branch. Tags often provide a stable name for a selected release commit, although tag objects and branch references have different roles. HEAD tells Git which checkout you are using. Read names as ways to locate objects rather than treating every visible name as another independent copy of the source files.

Understand attached and detached checkouts

When HEAD refers to main, a new commit advances main and your checkout follows that branch. After switching directly to an older commit or tag with --detach, HEAD refers directly to that commit. You can still inspect files and even create commits. The difference is that an ordinary branch name is not advancing to preserve that new chain automatically. If you intend to keep detached work, create a branch pointing to it before leaving. A detached state is useful for reviewing a release or running a historical comparison; it is not an error by itself.

Read first-parent and selected-parent notation

HEAD~1 means follow the first parent once; HEAD~2 follows that first-parent path twice. HEAD^ or HEAD^1 selects the first parent. HEAD^2 selects a second parent when the commit has one, such as a typical merge commit. It does not mean two commits earlier. These forms can coincide in a straight history and then differ at a merge. Before using a parent reference in an undo or comparison command, inspect the graph and confirm which path matches your intention. Do not assume the numbered parent represents a chronological distance.

Use commit ranges according to the command

For a history walk such as git log, A..B selects commits reachable from B but not from A. The symmetric range A...B selects commits reachable from either side but not both. Git diff uses these spellings differently: a two-endpoint comparison normally compares the endpoint trees, while its three-dot form compares B with a merge base of A and B. A range is therefore not a universal instruction to show the same set of objects in every command. State whether you want commits introduced by a branch or file changes measured from a shared starting point.

Select a historical file without switching branches

Git show HEAD:path reads a file from the selected commit snapshot. Replace HEAD with a tag, branch or unambiguous object name to inspect another version. This is convenient when you want to compare configuration or documentation without disturbing the working tree. Paths are relative to the repository context under Git's documented syntax; quote arguments where your shell treats punctuation specially. A file's presence today does not imply it existed in the selected commit. If the lookup fails, inspect the historical tree before concluding that the revision name is wrong.

Preserve experiments and recover a lost pointer

For a planned detached experiment, create a descriptive branch with git switch -c once you decide to keep the work. If you already switched away, the reflog may record the checkout and commit identities you need to inspect. Verify the recovered candidate's content before assigning a new branch. Reflogs are local records with retention rules, not a substitute for durable backups. The easiest prevention is to name valuable work while you still have it checked out. Keep uncommitted edits separate from this discussion: a branch reference preserves commits, not every unsaved or discarded editor change.

Sources and prerequisites

Review branches, history and reflog recovery. See the official revision syntax, switch, log and diff references for command-specific behavior.

Git HEAD, Detached HEAD and Revision Syntax Summary

  • Detached HEAD names a commit directly and can be used deliberately.
  • Tilde notation follows first parents; caret notation selects a parent.
  • Interpret ranges using the specific log or diff command's semantics.

Git HEAD, Detached HEAD and Revision Syntax Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Inspect a tagged snapshot in detached HEAD

Use a new Bash lab. The tag marks the first text snapshot, and main advances to the second. Switching to the tag detaches HEAD without moving main backward. Initialization and commit messages are incidental; the expected output records the final name lookup and historical file reads. Read each command's purpose before using similar syntax in a repository with important uncommitted work.

The name lookup prints HEAD because the checkout is detached rather than attached to a branch. The selected snapshot still contains Version one, while main continues to identify Version two. No reset was required to inspect the release. You have changed the checkout location, not deleted main's later commit. Return to main when finished or create a new branch if this older snapshot is the starting point for new work.

Terminal
mkdir revision-lab
cd revision-lab
git init -b main
git config user.name Learner
git config user.email learner@example.test
printf 'Version one\n' > notes.txt
git add notes.txt
git commit -m 'First snapshot'
git tag v1
printf 'Version two\n' > notes.txt
git add notes.txt
git commit -m 'Second snapshot'
git switch --detach v1
git rev-parse --abbrev-ref HEAD
git show HEAD:notes.txt
git show main:notes.txt
Output
HEAD
Version one
Version two

Common Git HEAD, Detached HEAD and Revision Syntax Mistakes

Reading HEAD^2 as two commits earlier

The number after a caret chooses a parent of the selected commit. Most ordinary commits have only one parent, so asking for their second parent fails. The number after a tilde counts first-parent steps instead. A merge diagram makes the distinction visible: its second parent usually follows the merged branch, while two first-parent steps follow the main-line chain. Confirm the relevant ancestry before using either form with a destructive operation.

Git HEAD, Detached HEAD and Revision Syntax in Real Projects

Branch from a detached HEAD and compare history

Continue at the detached v1 snapshot and create a branch for a maintenance experiment. Predict which content appears on the new branch. Then inspect the two-dot history from inspected to main. With the supplied straight history, only the second snapshot is reachable from main and not from inspected. More complicated merges can introduce additional ancestry, so explain the result through reachability rather than a fixed number of displayed rows.

Terminal
git switch -c inspected
git rev-parse --abbrev-ref HEAD
git show HEAD:notes.txt
git log --format=%s inspected..main
Output
inspected
Version one
Second snapshot

The branch is attached to the first commit, and the range lists the second commit's subject. Creating a branch did not copy every later change from main. If you commit maintenance work now, inspected advances along its own history. Compare that behavior with the core branching lesson and verify the branch graph before planning any merge back into main.

Git HEAD, Detached HEAD and Revision Syntax FAQ

Is detached HEAD an error I must fix immediately?

No. It is a valid checkout state useful for inspecting a specific commit or release. You can read files and run compatible tests normally. The important decision is whether you will create work that should be kept. If so, create a branch before leaving the resulting commit chain. If you only inspected the old snapshot, switch back to your intended branch after accounting for any working-tree changes you made during the inspection.

Are HEAD~2 and HEAD^2 the same thing?

They can name different commits, and one may not exist. The tilde form follows the first-parent chain twice. The caret form chooses the selected commit's second parent. In a straight history there is usually no second parent, while a merge often has one. Use a graph view or parent inspection to explain the selected relationship. Remembering that tilde counts steps and caret chooses parents is more useful than assuming both mean an older date.

Why do three dots mean different things in log and diff?

Each command interprets revision arguments for its own task. Log walks the commit graph and the symmetric three-dot range excludes shared reachable history. Diff compares file trees; its three-dot form measures the second endpoint against a merge base. That distinction is useful when reviewing a branch's changes without unrelated changes added to its base. Read the specific command reference whenever a range appears to show an unexpected set of commits or file differences.

Can a reflog rescue a commit made while detached?

Often the local reflog records the relevant movement, allowing you to locate and inspect the commit before creating a branch for it. That depends on the local records still being available and the objects not having been removed under retention and cleanup rules. Do not treat reflog retention as permanent storage. Name valuable experiments promptly, keep appropriate repository backups, and distinguish committed recovery from uncommitted edits that Git may never have stored.

Git HEAD, Detached HEAD and Revision Syntax Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Multiple choicemedium

In the supplied lab, what does inspected..main list after creating inspected at v1?

Git HEAD, Detached HEAD and Revision Syntax Quiz

2 questions to check what you learned.

  1. What changes when HEAD is attached to a branch and you commit?

    • The attached branch advances to the new commit
    • Every tag advances to the new commit
    • The existing parent commit's content is overwritten
  2. Which notation chooses the second parent of a merge commit?

    • HEAD~2
    • HEAD^2
    • HEAD:2