Detached HEAD
Normally, HEAD names the current branch, which names a Commit. Git can also place HEAD directly at a Commit. That state is called detached HEAD. It is useful for inspecting or testing an older snapshot, but new work made there needs a branch if you want an easy, durable name for it.
The mental model
Section titled “The mental model”On a branch: HEAD → master → C2 → C1Detached: HEAD ─────────→ C1 master → C2 → C1Switching to C1 directly moves HEAD; it does not move master. The Working Tree and Index are set up for C1, subject to Git’s protection of local changes. Files introduced only in C2 disappear from the Working Tree while at C1, but remain stored in C2.
Enter and inspect the state
Section titled “Enter and inspect the state”Use a disposable repository with a clean Working Tree and at least two Commits:
git status --shortgit switch --detach <older-commit-id>git log -1 --oneline --decorategit symbolic-ref HEADgit rev-parse HEADgit switch requires --detach when selecting a Commit directly. The older git checkout <commit-id> also enters detached HEAD, but switch --detach makes the intention explicit.
In the detached state, git symbolic-ref HEAD fails because HEAD does not contain a branch-ref name. git rev-parse HEAD still prints the current Commit ID. The failure is about the missing symbolic relationship, not a lost Commit.
git log normally walks back from the current HEAD; git log --oneline --decorate --all can also show Commits reached through branch refs such as master.
A new Commit while detached
Section titled “A new Commit while detached”Git allows Commits in this state. If we create C3 while detached at C1, the result is:
HEAD → C3 → C1master → C2 → C1The previously selected branch does not receive C3. While still detached, HEAD points to it directly. If you leave without giving C3 a branch or other durable reference, it can become hard to find through ordinary branch history. It is not deleted immediately; a local reflog may help find it for a time, but is not a permanent backup.
Give the Commit a branch name
Section titled “Give the Commit a branch name”While HEAD is at the new Commit:
git branch saved-workThis creates saved-work at the current Commit and leaves HEAD detached. To create the branch and attach HEAD to it instead, use:
git switch -c saved-workFrom another location, if you know the Commit ID, create a branch without switching:
git branch recovered-work <commit-id>In our training lab, the detached Commit 6bd2c6f was saved with git branch saved-work. After switching back to master, git log --oneline --decorate --all still showed saved-work at 6bd2c6f while HEAD was on master.
Reflog as a recovery clue
Section titled “Reflog as a recovery clue”git reflog -5 shows recent local HEAD movements. In the lab, it identified the checkout from master to an older Commit, the new detached Commit, and the checkout back to master. If no branch had been created, its ID could have been used to create a recovery branch while still available. Reflog retention and broader recovery procedures belong to a later checkpoint.
Common mistakes and safety
Section titled “Common mistakes and safety”- Assuming Git forbids Commits in detached HEAD.
- Assuming a detached Commit automatically belongs to the last branch used.
- Reading failure from
git symbolic-ref HEADas evidence the Commit was lost. - Leaving important detached work without creating a branch.
- Entering a historical snapshot with dirty local files without checking
git statusfirst. - Treating the reflog as a guaranteed long-term backup.
Summary
Section titled “Summary”Detached HEAD means HEAD points directly to a Commit rather than through a branch. New Commits move HEAD but leave branch tips unchanged. Create a branch at any detached work you want to keep, then switch back freely. A reflog can help locate recent movements, but a named branch is the clearer way to preserve access.
Knowledge check
Section titled “Knowledge check”You commit C3 while detached at C1. Where does master point?
It remains at its previous Commit. HEAD moves directly to C3, whose parent is C1.
How do you save the current detached Commit without changing HEAD?
Run git branch <new-name> while at that Commit. The new branch points there, and HEAD stays detached.