Detached HEAD
In short
A detached HEAD is a Git state in which you have checked out a specific commit instead of a branch, so any new commits you make don't belong to any branch.
What is a detached HEAD in Git?
In Git, HEAD is a pointer to whatever you currently have checked out. Normally it points to a branch, such as main, and the branch points to a commit, so when you commit, the branch moves forward and HEAD moves with it. In a detached HEAD state, HEAD points directly at a commit instead, and no branch is attached.
You enter this state when you check out something that isn't a local branch: a commit hash, a tag like v2.1.0, or a remote-tracking branch such as origin/main, using git checkout or git switch --detach. Commands like git bisect and git rebase also detach HEAD temporarily while they work. Git prints a warning that you are in 'detached HEAD' state, and git status reports 'HEAD detached at' followed by the commit or tag.
It is like reading an old edition of a book from the archive: perfectly fine for looking around, running tests, or building an old release. You can even edit and commit, but those commits have no branch name pointing to them, so once you switch away they become hard to find and are eventually removed by Git's garbage collection. To keep that work, create a branch right where you are with git switch -c <name>.
A detached HEAD is often mistaken for an error or a broken repository, but it is a normal, useful state; the only risk is losing commits made while in it. The key difference from being on a branch is what moves when you commit: on a branch, the branch pointer follows your new commit, while in detached HEAD nothing does except HEAD itself. If you have already switched away and left commits behind, git reflog lists their hashes so you can attach a branch to them.
Key takeaways
HEADnormally points to a branch; in a detached HEAD state it points directly at a commit.- Checking out a commit hash, a tag, or a remote-tracking branch detaches
HEAD. - It is safe for inspecting, testing, or building old versions.
- Commits made while detached belong to no branch and can be lost after you switch away.
git switch -c <name>saves detached work on a new branch, andgit reflogcan recover it later.
Example
# Inspect an old release: this detaches HEAD
git checkout v2.1.0
# HEAD is now at 3c4d5e6 Release 2.1.0
git status
# HEAD detached at v2.1.0
# Made commits here that you want to keep? Put them on a new branch
git switch -c fix/old-release
# Nothing to keep? Just go back to your branch
git switch mainReaders ask
How do I fix a detached HEAD in Git?
If you made no commits you want to keep, switch back to a branch with git switch main. If you did make commits, first run git switch -c <new-branch> to put them on a branch, then merge or push that branch as usual.
Can I lose work in a detached HEAD state?
Commits made while detached are at risk, because no branch points to them. After you switch away they can still be found with git reflog for a while, 30 days by default, before Git's garbage collection may delete them, so create a branch if you want to keep them.
Why does checking out a tag cause a detached HEAD?
A tag is a fixed pointer that is not supposed to move, so Git can't let new commits advance it the way a branch does. Instead it points HEAD straight at the tagged commit, leaving any new commits unattached until you create a branch.
See also
- BranchVersion Control, p. 2A branch in Git is an independent line of development that lets you work on a feature or fix in isolation, without affecting the main code until you merge it.
- Git TagVersion Control, p. 23A Git tag is a named, permanent pointer to a specific commit, most often used to mark release versions such as v1.0.0 in a repository's history.
- CommitVersion Control, p. 5A commit is a saved snapshot of a project's files in Git, recorded with a unique ID, an author, a timestamp, and a message describing what changed.
- Git BisectVersion Control, p. 11Git bisect is a Git command that uses binary search through commit history to find the exact commit that introduced a bug, testing only a few commits.
- Git ResetVersion Control, p. 20Git reset is a Git command that moves the current branch back to an earlier commit and, depending on its mode, also resets the staging area and your files.
- HEADVersion Control, p. 27HEAD is Git's pointer to what you have checked out, normally the current branch, which points to its latest commit; new commits are added where HEAD points.
Spotted a mistake or something missing on this page?Suggest an edit