TraceDynamics
Version Control

Git Detached HEAD: What It Means and How to Recover Your Work

Seeing 'You are in detached HEAD state' in Git? It is not an error. Learn what it means, how to save commits made in it, and how to find ones you left behind.

On this page
  1. What "detached HEAD" means
  2. How you end up detached
  3. If you only looked around
  4. If you made commits and are still detached
  5. If you already switched away
  6. If you lost the hash
  7. When detached HEAD is exactly what you want
  8. Related fixes

You ran a Git command and got a wall of text that begins like this:

Output
Note: switching to 'v1.0'.

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.

It sounds alarming. It is not an error, and nothing has been lost. This guide explains what the state is, and then the one situation that can cost you work: committing while detached and then moving away.

What "detached HEAD" means#

HEAD is Git's pointer to "where you are right now". Normally it points at a branch, and the branch points at a commit. You can see this in the file itself:

Shell
cat .git/HEAD
Output
ref: refs/heads/main

When HEAD is detached, it points straight at a commit instead of at a branch:

Shell
cat .git/HEAD
Output
b61305c9ec4de1aaea61a5477c5ca6a52bd7d7db

That is the whole idea. Because no branch is attached, new commits made here are not recorded on any branch. That is fine for looking around, and a trap if you forget.

How you end up detached#

Any command that checks out something that is not a local branch detaches HEAD:

  • git checkout <commit-hash>, to look at an old version
  • git checkout v1.0 or any other tag
  • git switch --detach (the explicit form)
  • checking out a remote branch directly, such as origin/main, rather than a local branch
  • a rebase that stops for a conflict (git status then reports "rebase in progress", and HEAD is detached while it runs)

You can tell where you are at any time:

Shell
git status
git branch --show-current
Output
HEAD detached at v1.0

git branch --show-current prints nothing at all when you are detached, which is a handy check in scripts.

If you only looked around#

You did not commit anything and just want to leave. Switch back to a branch:

Shell
git switch main

Or use git switch -, which we confirmed returns you to the branch you came from. Nothing needs saving.

If you made commits and are still detached#

This is the easy case, because you still know where you are. Turn your current position into a branch:

Shell
git switch -c keep-this-work
Output
Switched to a new branch 'keep-this-work'

Your commits are now on keep-this-work, safe and reachable. Git suggests exactly this command in the message it printed when you detached.

If you already switched away#

Here is the dangerous version. You committed while detached, then ran git switch main. Git does not let it pass silently. It prints a warning with the hash of the commit it is leaving behind:

Output
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  5a13475 Work done while detached

If you want to keep it by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> 5a13475

If you saw that and still have the hash, the fix is one command:

Shell
git branch rescue 5a13475

Your commit is now the tip of a branch called rescue, and it is safe again.

If you lost the hash#

You scrolled past the warning and the terminal is gone. The commit is still there, and Git keeps a log of everywhere HEAD has been, called the reflog:

Shell
git reflog
Output
66b9248 HEAD@{0}: checkout: moving from 5a134757c6a9fa84704af01f12165b1ff6d22f6b to main
5a13475 HEAD@{1}: commit: Work done while detached
b61305c HEAD@{2}: checkout: moving from main to v1.0
66b9248 HEAD@{3}: commit: Commit 3
abcf7bb HEAD@{4}: commit: Commit 2
b61305c HEAD@{5}: commit (initial): Commit 1

Find the line that matches your work, 5a13475 HEAD@{1}: commit: Work done while detached, and give it a branch:

Shell
git branch rescue 5a13475

You can also point at it by its reflog position. Right after leaving, git branch rescue 'HEAD@{1}' created a branch at the same commit we had just left, but reflog positions shift with every later command, so prefer the hash.

The reflog is a safety net, not a vault. Commits that no branch reaches are eventually removed by Git's garbage collection, so rescue them promptly rather than leaving them for later.

When detached HEAD is exactly what you want#

Plenty of work is meant to happen detached:

  • Bisecting a bug. Checking out old commits to find where something broke.
  • Building from a tag. CI systems often check out a specific commit or tag, so you will see this message in build logs.
  • Trying something throwaway. Experiment freely, then switch back to discard it.

In every one of these, the state is doing its job.

If your problem is the opposite, you want to undo something you did commit, see how to uncommit in Git. If a rebase left you detached partway through, undoing a rebase covers getting back. And if you committed on the wrong branch altogether, moving a commit to another branch is the cleaner fix.

Advertisement
esc

↑↓ navigate↵ openesc close