Detached HEAD State
"Detached HEAD" sounds scary, but it's a normal Git state. Learn what it means, why it happens, how to fix it, and how to recover any work you've done while detached.
In Git, HEAD is a special pointer that tells you which commit you're currently viewing or working on. Normally, HEAD points to a branch name, and that branch points to a commit. For example, when you're on the main branch, HEAD points to "main," and "main" points to the latest commit. This is called an "attached HEAD" state.
When you run commands like git checkout main or git switch main, you're attaching HEAD to that branch. When you make new commits, the branch pointer moves forward, and HEAD moves with it automatically.
Normal (Attached) State:
HEAD → main → commit A → commit B → commit C (latest)
.git/HEAD. You can even look at it directly with cat .git/HEAD.
Detached HEAD occurs when HEAD points directly to a commit hash instead of pointing to a branch name. In this state, you're no longer on any branch. Git displays a warning message telling you that you're in detached HEAD state and that any new commits you make won't belong to any branch.
Being in detached HEAD isn't dangerous—it's a feature. It allows you to explore old commits, inspect code from the past, or test things without affecting any branches. The problem is that new commits made while detached are "unreachable" from any branch, making them easy to lose if you switch away without creating a branch.
Detached HEAD State:
HEAD → commit C (directly, no branch)
main → commit B (unchanged)
You enter detached HEAD whenever you check out something that isn't a local branch name. The most common ways are:
Checking out a commit hash: git checkout a1b2c3d moves HEAD directly to that commit.
Checking out a tag: git checkout v1.0 moves HEAD to the commit tagged v1.0.
Checking out a remote branch without creating a local branch: git checkout origin/main puts you in detached HEAD.
Checking out a commit relative reference: git checkout HEAD~3 moves HEAD three commits back.
# These commands cause detached HEAD:
$ git checkout a1b2c3d # Checkout specific commit
$ git checkout v2.0 # Checkout a tag
$ git checkout HEAD~2 # Checkout parent commit
$ git checkout origin/feature # Checkout remote branch
git switch -c mybranch origin/mybranch or git checkout -b mybranch origin/mybranch to create a local tracking branch.
Detached HEAD isn't a mistake—it's a useful tool for several scenarios. You might want to inspect the state of your code at a specific point in history. By checking out an old commit, you can browse files, run tests, or debug issues without affecting your current work.
You might also use detached HEAD to experiment temporarily. You can make test commits, see how things work, and then discard them by simply switching back to your branch—the experimental commits will be garbage-collected later.
Another common use is examining tags. When you check out a tag (like git checkout v1.0), you enter detached HEAD. This lets you see exactly what code was released at that version without creating a branch.
If you're in detached HEAD and haven't made any new commits, fixing it is simple. Just check out or switch to a branch:
# Switch back to main branch
$ git switch main
# Or checkout a branch
$ git checkout main
# Check which branch you want to return to
$ git branch
* (HEAD detached at a1b2c3d)
main
feature
$ git checkout main
Switched to branch 'main'
If you've made commits while detached and want to keep them, you need to create a branch at that position before switching away. Otherwise, those commits become unreachable and may eventually be garbage-collected.
# First, create a branch at your current position
$ git branch my-new-branch
# Or create and switch to it in one command
$ git switch -c my-new-branch
# Now you're on a branch with all your commits safe
What if you already switched away from detached HEAD without creating a branch? Don't panic—your commits aren't gone forever. Git keeps them in the reflog for about 90 days.
First, find the commit hash of your lost work using git reflog. Look for entries that show commits you made while in detached HEAD. They'll be listed with their hashes. Once you have the hash, create a branch at that commit to restore your work.
# Find your lost commits in the reflog
$ git reflog
a1b2c3d HEAD@{0}: checkout: moving from main to HEAD~2
e4f5g6h HEAD@{1}: commit: Important work in detached state
i7j8k9l HEAD@{2}: commit: More work in detached state
m9n0o1p HEAD@{3}: checkout: moving from feature to main
# Create a branch at the lost commit
$ git branch recovered-work e4f5g6h
# Switch to the new branch
$ git checkout recovered-work
You can always check whether you're in detached HEAD by running git status or git branch. Both commands clearly indicate detached state.
# git status shows detached HEAD warning
$ git status
HEAD detached at a1b2c3d
nothing to commit, working tree clean
# git branch shows no current branch
$ git branch
* (HEAD detached at a1b2c3d)
main
feature
# git symbolic-ref HEAD shows what HEAD points to
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref
# For attached HEAD, it shows the branch name
$ git symbolic-ref HEAD
refs/heads/main
(detached) or the commit hash instead of a branch name.
Create a branch before experimenting. If you want to try something risky or explore old code, create a branch first. git checkout -b experiment keeps your work safe.
Use git switch instead of checkout. The newer git switch command is more explicit. It won't let you enter detached HEAD without warning, and it has a -c flag to create branches.
Always check your branch before committing. Run git status or git branch before making commits to ensure you're on the right branch.
Tag important commits. If you find a commit worth remembering, tag it: git tag my-important-point. Tags won't be lost.
Push branches to GitHub. The safest way to preserve work is to push it. Even if you lose your local copy, GitHub retains your branches.
git branch save-my-work. Then switch to any other branch: git checkout main. Your work is now saved in the new branch.git reflog to find the commit hashes of your lost work, then create a branch at that commit: git branch recover . Your commits are restored.git switch was introduced in Git 2.23 to be more intuitive. git switch branch moves HEAD to a branch. git switch -c new-branch creates and switches to a new branch. git checkout still works but does many things—switching branches, restoring files, and entering detached HEAD.Detached HEAD is a feature, not a bug. Use it to explore history, test old versions, or experiment safely. Just remember to create a branch when you want to keep your work.