Docs Library

Understanding Detached HEAD State

Explain what detached HEAD is, how you enter this state, and how to safely exit detached HEAD while preserving your work.

Who This Is For
  • Readers who want the history model before advanced commands
Prerequisites
  • A basic sense that commits are not just a file list
Common Risks
  • Treating a concepts page like a command how-to

In One Sentence

A detached HEAD means HEAD points directly to a commit instead of a branch name. It's not an error — it's Git's "temporary browsing mode" that lets you inspect history, but requires deliberate action to exit safely.

Normal vs Detached HEADTop: HEAD points to a branch which points to a commit (normal). Bottom: HEAD points directly to a commit (detached).
HEAD Points To
HEAD -> refs/heads/feature/login
Branch: feature/login -> F
Remote Ref: origin/main -> D
Tag: v2.0.0 -> D
Detached HEAD
HEAD -> F
DFG

What Is HEAD

Before understanding detached HEAD, you need to know what HEAD normally is.

Normal State: HEAD → Branch → Commit

In a normal Git repository, HEAD points to a branch name, and the branch name points to a commit. When you run git commit, Git creates a new commit, moves the current branch pointer to it, and HEAD still points to that branch — this is why branches advance naturally with each commit.

Detached HEAD: HEAD → Commit

When you checkout a specific commit instead of a branch, HEAD points directly to that commit. You are not on any branch. Git will print a warning in the terminal indicating you're in detached HEAD state.

How to Enter Detached HEAD

These operations enter detached HEAD:

# checkout a specific commit hash
git checkout <commit-hash>

# checkout a tag
git checkout v1.0.0

# checkout a remote-tracking branch
git checkout origin/main

# use revision syntax
git checkout HEAD~3

# use switch with --detach
git switch --detach <commit-hash>

Why These Trigger Detached HEAD

Because the target is not a local branch name. Tags, remote branches, and commit hashes are not movable branch pointers, so Git cannot attach HEAD to something that would "advance automatically."

Working in Detached HEAD

What You Can Do

  • Inspect historical commits: the most common use case
  • Run temporary experiments: try changes and see the results
  • Build and test old versions: confirm when a bug was introduced
  • Emergency patches against an old state

Things to Watch For

You can still make commits in detached HEAD:

# modify and commit while detached
echo "experimental change" > test.txt
git add test.txt
git commit -m "experimental commit"

The commit graph becomes:

HEAD → C4 (new commit, only reachable via HEAD)
       │
       C3 ← main

C4 is only referenced by HEAD. If you switch back to main, HEAD leaves C4 behind, making C4 unreachable.

How to Safely Exit Detached HEAD

Option 1: No Changes to Keep

If you were just browsing:

# switch back to a branch
git switch main

# or
git checkout main

Option 2: Keep Changes (Create a Branch)

If you made commits in detached HEAD, create a branch before switching away:

# create a branch at current HEAD
git switch -c my-experiment

# or
git branch my-experiment
git switch my-experiment

After creating the branch:

HEAD → my-experiment → C4
                        │
                        C3 ← main

C4 is now referenced by my-experiment and will not be lost.

Option 3: Cherry-pick to an Existing Branch

If you made several commits in detached HEAD and want them in an existing branch:

# note the commit hashes first
git log --oneline -5

# switch to target branch
git switch main

# cherry-pick the needed commits
git cherry-pick <commit-hash>

Risk Boundaries

Key Rule: Ensure Commits Are Referenced Before Switching Away

If you make commits in detached HEAD and switch back to a branch without creating a branch to reference them first, those commits become unreachable and may be garbage collected. As long as you run git branch <name> before switching away, there is no risk of losing work.

ScenarioRisk
Only viewing, no changesNone — just switch away
Changed but didn't commitUnstaged changes carry over or produce a warning on switch
Committed but no branch createdCommits become unreachable (may be GC'd)
Committed and created a branchSafe — same as normal branch work
Multiple commits, no branchAll commits unreachable, but recoverable via reflog

Best Practices for Common Scenarios

bisect Naturally Uses Detached HEAD

git bisect runs entirely in detached HEAD — this is expected. The bisect end command returns you to your original branch.

Reviewing Old Release Code

# checkout the v2.0.0 tag
git checkout v2.0.0

# switch back when done
git switch main

In CI and Scripts

CI environments frequently checkout specific commits. Use git checkout --detach to make the intent explicit.

Continue Learning

After understanding detached HEAD, continue with:

  1. git switch vs git checkout differences
  2. git reflog — recovering lost commits from detached HEAD
  3. git bisect — how it leverages detached HEAD for binary search
  4. git branch — creating branches to preserve experimental work