GitDetached HEAD State

Detached HEAD State

“Detached HEAD” is one of the most-feared Git messages, but it is harmless if you understand it. It just means HEAD is pointing directly at a commit instead of at a branch. Nothing is broken, no work is lost — but any new commits you make in this state will not belong to any branch, which is where the danger lies.

What HEAD normally is

Normal: HEAD → branch → commit

Text
HEAD ──▶ refs/heads/main ──▶ commit C   ◀── main
                                A───B───C

When you commit, Git advances the branch HEAD points to. That is how branches grow.

Detached: HEAD → commit directly

HEAD points at a commit, not a branch

Text
HEAD ──▶ commit B
        A───B───C   ◀── main

You enter this state when you check out a commit, tag, or remote-tracking ref — anything that is not a local branch.

How you end up here

Common triggers

Bash
git checkout 1f9ab2c       # specific commit
git checkout v1.0          # a tag
git checkout origin/main   # remote-tracking branch (read-only)
git switch --detach 1f9ab2c

# Git will warn:
# Note: switching to '1f9ab2c'.
# You are in 'detached HEAD' state. You can look around, make experimental
# changes and commit them, and you can discard any commits you make in this
# state without impacting any branches by switching back to a branch.
Why it exists
  • You may want to inspect an old commit — check what the code looked like at a specific point.

  • You may want to run a test against a tagged release without making changes.

  • You may want to experiment with changes you do not intend to keep.

  • CI/CD tools often check out a specific commit hash; their builds run in detached HEAD.

The danger
Warning
Any commits you make while detached are **not on any branch**. If you switch to another branch without recording them somewhere, they become unreachable. Git will keep them in the reflog for ~90 days, but after garbage collection they are gone.

Detached, then made commits

Text
HEAD ──▶ D───E
                 \
                  C   ◀── main
                  |
                  B
                  |
                  A

After 'git switch main':
HEAD ──▶ main ──▶ C

D and E are orphaned. Reachable only via reflog.
The safe way out: create a branch

Promote your experimental commits

Bash
# You made commits D and E in detached HEAD
git switch -c keep-my-work
# Now HEAD points to 'keep-my-work' which points to E
# Your commits are saved
The other safe way: discard

If you don't want the commits, just switch away

Bash
git switch main
# Warning: you are leaving 2 commits behind, not connected to any of your
# branches:
#   abc1234 Experimental commit D
#   def5678 Experimental commit E
# If you want to keep them by creating a new branch, this may be a good time
# to do so with:
#   git branch <new-branch-name> def5678
Recovering after the fact

Even after you've switched, the reflog can save you

Bash
git reflog
# def5678 HEAD@{0}: checkout: moving from def5678 to main
# def5678 HEAD@{1}: commit: Experimental commit E
# abc1234 HEAD@{2}: commit: Experimental commit D
# 1f9ab2c HEAD@{3}: checkout: moving from main to 1f9ab2c

# Recover by creating a branch at that hash
git switch -c recovered-work def5678
How to know you’re detached

Bash
git status
# HEAD detached at 1f9ab2c
# nothing to commit, working tree clean

git branch
# * (HEAD detached at 1f9ab2c)
#   feature-x
#   main
Intentional detached HEAD use cases
  • “What did this look like at v1.0?”git checkout v1.0, browse files, git switch - to come back.

  • Running CI on a specific commit — pipelines check out by SHA in detached HEAD.

  • Bisectinggit bisect works in detached HEAD as it walks through history.

  • Quick test — try a fix at an old commit without committing anything, then return to main.

Tags and detached HEAD
Checking out a tag puts you in detached HEAD because tags are immovable — Git won’t advance one when you commit. If you want to start work from a tagged release, immediately create a branch: `git switch -c hotfix-from-v1 v1.0`.
The general rule

If you only want to look, detached HEAD is fine. If you start making commits, create a branch first:

Bash
# Instead of:
git checkout 1f9ab2c
# (make commits...)

# Do:
git switch -c temp-work 1f9ab2c
# (make commits — they're on a branch, safe)
Tip
Detached HEAD is not an error message — it is Git being precise about your situation. Treat it as a normal mode you sometimes need, and remember the rescue command: git switch -c <name>.