Normally .git/HEAD contains a reference to a branch:
ref: refs/heads/main
In detached mode it holds the commit SHA directly:
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
HEAD is not attached to any branch. Every command that writes "to the
current branch" (git commit, git pull) loses its clear target.
How you get here
git switch --detach v1.0 # explicit, on a tag
git checkout HEAD~3 # implicit, on an old commit
git checkout origin/main # implicit, on a remote branch
git checkout <sha> # implicit, on a specific commit
All of these are legitimate. You may want to read the code as it was at release time, find the offending commit via bisect, or run a quick local experiment.
What is safe to do here
- Read files.
- Run tests and builds.
- Make local edits to the working tree (but do not commit them).
What is risky
- Committing. The commit is created and HEAD moves to it, but no
branch points at the new commit. The moment you switch to any branch,
the new commit becomes unreachable and will vanish in
git gcafter 30 days.
If you committed here, how to recover
Create a branch from the current HEAD:
git switch -c rescue
# or
git branch rescue
Now rescue points at your commits and they are safe. From there you
can run git switch main && git merge rescue or cherry-pick as needed.
Pitfalls
- Git prints a large warning when you enter detached state. Do not ignore it. Tracking down "where did those commits go" later is harder.
git reflogremembers everything. Even if the commits appear "lost", reflog shows their SHAs, and you can create a branch after the fact.- A failed
git rebasesometimes leaves you in detached state. If you see an unexpected detached HEAD after a rebase, rungit rebase --abortor recover via reflog.