The detached HEAD state occurs when HEAD points directly to a commit instead of a branch. This is not an error but a warning that any new commits you make will not belong to any branch and could be lost when you switch branches.
In Git, HEAD is a pointer that normally references the current branch, which in turn points to the latest commit on that branch. When you're in a "detached HEAD" state, HEAD points directly to a specific commit rather than a branch. This state is not an error - it's a valid and sometimes useful Git state. Git shows this message to warn you that if you make commits in this state, they won't be associated with any branch. If you later checkout a different branch without saving your work, those commits become "orphaned" and may eventually be garbage collected. The detached HEAD state is actually useful for temporarily exploring historical commits, testing old versions of code, or making experimental changes you may or may not want to keep.
First, verify that you're in a detached HEAD state and see what commit you're on:
git status
git log --oneline -1Git will explicitly tell you if you're in a detached HEAD state and show you the current commit.
If you haven't made any changes you want to keep, simply switch back to your main branch:
git checkout main
# or
git checkout master
# or any other branch you want to return to
git switch main # Modern alternativeThis immediately reattaches HEAD to the branch.
If you made commits in the detached HEAD state that you want to keep, create a new branch from your current position:
git checkout -b my-new-branch
# or using the modern switch command
git switch -c my-new-branchThis creates a new branch pointing to the current commit and checks it out, preserving all your work.
If you already left the detached HEAD state and lost track of commits, you can recover them using the reflog:
# View the reflog to find your commits
git reflog
# Find the commit hash you want to recover
# Then create a branch from it
git branch recovered-work <commit-hash>
git checkout recovered-workThe reflog keeps a history of all HEAD movements for about 30 days by default.
Once you've saved your detached HEAD commits to a branch, you can merge them into your main development branch:
git checkout main
git merge recovered-work
# Or use cherry-pick for specific commits
git cherry-pick <commit-hash>After merging, you can delete the temporary branch if no longer needed.
### When Detached HEAD is Useful
The detached HEAD state is intentionally designed for certain workflows:
- Code archaeology: Exploring historical versions of your codebase without affecting branches
- Testing old versions: Checking if a bug existed in a previous release
- Bisecting: Git bisect puts you in detached HEAD state while hunting for bugs
- Building releases: CI/CD systems often checkout specific tags in detached HEAD state
### Preventing Accidental Detached HEAD
To avoid accidentally entering detached HEAD state:
# Instead of checking out a tag directly
git checkout v1.0.0 # Creates detached HEAD
# Create a branch from the tag
git checkout -b release-1.0.0 v1.0.0 # Stays on a branch
# Instead of checking out a remote branch directly
git checkout origin/feature # Detached HEAD
# Create a local tracking branch
git checkout -b feature origin/feature # Proper branch### The git switch Command
Git 2.23+ introduced git switch as a safer alternative to git checkout for branch operations. It refuses to detach HEAD by default:
git switch main # Switch branches safely
git switch -c new-branch # Create and switch
git switch --detach v1.0.0 # Explicit detach requiredUsing git switch makes it harder to accidentally enter detached HEAD state.
warning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server