Git “You are in ‘detached HEAD’ state”: what it means and how to get out safely
Normally HEAD points at a branch, and the branch points at a commit. “Detached” means HEAD points straight at a commit, with no branch name in between. Nothing is broken, but new commits have no name holding on to them.
What git is telling you
$ git checkout v2.1.0
Note: switching to 'v2.1.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.
HEAD is git’s “you are here” marker. On a branch, .git/HEAD contains ref: refs/heads/main; when you commit, the branch moves forward and HEAD follows it. When detached, .git/HEAD contains a bare commit hash (a SHA-1 like those the hash generator makes). Commits still work, but when you switch away, no branch remembers them.
How you ended up here
| You ran | Why it detaches |
|---|---|
git checkout a1b2c3d | A commit hash is not a branch |
git checkout v2.1.0 | Tags are fixed labels; they never move, so you can’t be “on” one |
git checkout origin/main | Remote-tracking branches are read-only copies of the server’s state |
| A rebase that stopped on a conflict | Git replays commits detached, then re-attaches when the rebase finishes |
git submodule update | Submodules are checked out at the exact commit the parent repo recorded |
| CI (GitHub Actions, GitLab, Jenkins) | Pipelines check out the exact commit being tested, so git branch shows (HEAD detached at …) |
Just looking? Go back to a branch
git switch main # or: git checkout main
git switch - # back to wherever you were before
If you only looked around or ran tests, that’s all. Any files you edited but didn’t commit come with you, unless they clash; then git refuses and you can git stash first.
Made commits? Keep them before you leave
git switch -c my-fix # new branch right here; your commits now have a name
git switch main
git merge my-fix # or open a pull request from my-fix
Want them on an existing branch instead? Note the hashes with git log --oneline, switch to the branch and git cherry-pick <hash> each one.
Already switched away and the commits “vanished”?
They aren’t gone yet. Git keeps unreferenced commits for at least about two weeks (often 30 days or more) before garbage collection. Git usually even prints a warning with the hash as you leave. Otherwise ask the reflog, git’s diary of where HEAD has been:
git reflog
# 3f9e2a1 HEAD@{0}: checkout: moving from 7c41d0b to main
# 7c41d0b HEAD@{1}: commit: fix the parser
git branch rescued 7c41d0b
Compare what you rescued with git diff main rescued, or paste two versions into the text diff tool.
In CI or a submodule
- CI: detached is normal. Use the variable your system gives you (
GITHUB_REF_NAME,CI_COMMIT_REF_NAME) rather thangit branch --show-current, which prints nothing when detached. To push from CI, push explicitly:git push origin HEAD:main. - Submodules: to work inside one,
cdinto it andgit switch mainbefore committing, then commit the new submodule pointer in the parent repo.git submodule update --remote --mergekeeps them on a branch.
Check where HEAD points
git status # "HEAD detached at v2.1.0" or "On branch main"
git symbolic-ref -q HEAD # prints refs/heads/main, or fails when detached
git branch --show-current # empty output = detached
Pushes being rejected after you rescue your work? See git push rejected (non-fast-forward).
error: src refspec main does not match any on push usually means the branch name does not exist locally yet: src refspec main does not match any.
Questions
Is detached HEAD bad?
No. It is a normal state for looking at old versions, tags and CI builds. The only risk is making commits and then switching away without creating a branch, which leaves those commits without a name.
How do I fix detached HEAD in git?
If you made no commits, run git switch main (or the branch you want). If you made commits you want to keep, run git switch -c new-branch-name first, then merge that branch.
How do I recover commits made in detached HEAD?
Run git reflog, find the hash of your last commit, and run git branch rescued <hash>. Unreferenced commits are normally kept for weeks before git deletes them.
Why does checking out a tag give detached HEAD?
A tag is a fixed label on one commit and never moves. Since a new commit can't move the tag, git points HEAD directly at the commit. Use git switch -c branch-name v2.1.0 if you want to make changes starting from a tag.
Published .