The Detached HEAD State: Why Git Won't Push and How to Fix It
Have you made changes in your repository only to realize git push fails because you are in a Detached HEAD state? This happens because when you run git checkout <commit-hash>, you are telling Git to look at a specific point in history, not a moving branch name.
In this state, any new commits you make are not part of any branch, making them very easy to lose. The solution is to create a new branch at that commit to save your work.
Understanding the Detached HEAD State​
The pointer called HEAD determines what branch or commit you are currently looking at.
- Attached HEAD (Normal):
HEADpoints to a branch name (likemainorfeature-x), which in turn points to a commit. When you write new commits, the branch pointer automatically moves forward. - Detached HEAD:
HEADpoints directly to a commit hash instead of a branch. When you commit, the new commit is created andHEADmoves to it, but no branch name tracks it. If you switch branches, your new commits will become dangling commits and can be lost.
Common Causes:​
- Checking out a specific commit:
git checkout 1a2b3c4 - Checking out a tag:
git checkout v1.0.0 - Viewing a remote branch directly:
git checkout origin/main
Step 1: Identify if You Have a Detached HEAD​
You can confirm whether you are in this state by running:
git status
If you are detached, the output will warn you:
HEAD detached at ABCDEF1
nothing to commit, working tree clean
Step 2: The Solution (Save Your Work)​
Depending on whether you want to save or discard your edits, choose one of the options below.
Option A: Save Your Commits to a New Branch (Recommended)​
If you have made edits and committed them while detached, give those commits a permanent home:
- Create and switch to a new branch from your current detached position:
# Preferred modern command:
git switch -c my-new-feature-branch
# Or using the older checkout command:
git checkout -b my-new-feature-branch - Push your new branch to the remote repository:
git push -u origin my-new-feature-branch
If you want to integrate this work into an existing branch (like main), check out the target branch and merge the new branch:
git switch main
git merge my-new-feature-branch
Option B: Discard Your Changes and Return to a Branch​
If you got into this state by mistake, have no work to save, and just want to return to your normal branch:
# 1. Forcefully discard any uncommitted local edits
git reset --hard
# 2. Switch back to your main branch
git switch main
What Happens If You Forgot to Save? (Reflog Recovery)​
If you made commits while detached, switched to another branch, and your commits vanished, they are now dangling commits. They are not yet deleted, but they are no longer reachable by any branch pointer. Eventually, Git's garbage collection (git gc) will delete them.
To recover them immediately:
- Find the commit hash of your lost work using
git reflog:Look for the commit message you wrote:git reflogABCDEF1 (HEAD -> main) HEAD@{0}: commit: My lost commit message - Recover it by creating a branch pointing directly to that hash:
git switch -c recovered-branch ABCDEF1
Best Practice: Avoid Detaching Entirely​
When you want to make changes based on an older commit, always create a branch before you start working:
# 1. Start from the specific commit
git checkout <commit-hash>
# 2. IMMEDIATELY create and switch to a new branch
git switch -c hotfix-on-old-version
# 3. Now make changes, commit, and push normally
git add .
git commit -m "Fix applied safely"
git push -u origin hotfix-on-old-version
Sources​
- [1] Git Documentation: git-checkout Detached HEAD
- [2] Atlassian Git Tutorials: Understanding HEAD in Git
- [3] Git Glossary: HEAD
- [4] Git Documentation: Garbage Collection (git gc)
- [5] Git Documentation: git-log Formatting Options
