Detached HEAD Recovery
Understand detached HEAD and recover from it — Git Tutorial. Learn what causes a detached HEAD, how to inspect your state, and safe recovery paths.
Focus: understand detached head and recover from it
You’re mid-feature, you checkout a commit hash to peek at an old version, and suddenly git status tells you you’re not on any branch. Your next commit seems to vanish into thin air. This is the infamous detached HEAD — and it’s scary only until you understand it. In this lesson, you’ll learn exactly what a detached HEAD is, why it happens, and how to recover from it safely using branches, tags, and the reflog. By the end, you’ll handle detached HEAD like a pro — and know how to turn any “lost” commit into a saved one.
The problem this lesson solves
A detached HEAD is Git’s way of telling you that your HEAD is pointing directly at a commit, not at a branch reference. When you git checkout <sha>, HEAD detaches — and any commit you make there is orphaned the moment you switch away. Without recovery, that work feels lost.
The pain is real: you experiment on an old release, make a couple of commits, then git checkout main — and your changes exist nowhere. You can’t see them in git branch. Panic sets in.
This lesson removes that panic. You’ll learn how to recognize a detached HEAD, inspect your new commits, and either preserve them with a new or existing branch, discard them cleanly, or recover them via the reflog — even if you already switched away.
Core concept / mental model
Think of branches as sticky notes pointing to commits. HEAD is your current location — normally, it points to a sticky note (a branch). In a detached HEAD state, Git removes the sticky note and HEAD points directly at the commit itself. The commit is still there, but without a branch, it’s not referenced — and unreferenced commits can be garbage-collected.
Normal:
main --> C3 (HEAD)
Detached:
HEAD --> C2
main --> C3
The key insight: a detached HEAD is not an error — it’s an unlabeled pointer. It’s perfect for inspection or historical work, but dangerous for new commits unless you attach a branch.
How it works step by step
Detaching: what triggers it
HEAD detaches in three common ways:
- Running
git checkout <commit-sha> - Running
git checkout <tag> - Running
git checkout HEAD~2(or any commit-ish expression that isn’t a branch name)
All three place HEAD at a commit directly, bypassing any branch label.
Recognizing it
Git prints a warning on checkout, and git status shows:
HEAD detached at 4a3b9c2
Committing while detached
New commits simply advance HEAD. They’re stored in .git/objects but not referenced by any branch.
Recovering: your options
- Create a new branch from the current commit: preserves your work permanently.
- Point an existing branch at the current commit: repurposes a branch to include your new work.
- Return to a branch and keep no changes: if you don’t need the work.
- Use the reflog to find lost commits after you’ve switched away.
Hands-on walkthrough
Let’s walk through a full scenario from detachment to recovery.
1. Set up a test repo
mkdir detached-demo && cd detached-demo
git init
echo "initial" > file.txt
git add file.txt
git commit -m "Initial commit"
echo "more" >> file.txt
git commit -am "Second commit"
2. Detach HEAD
# Get the latest commit SHA
git log --oneline HEAD~1 -1
# Output: <sha> Second commit
# Detach at the second commit
git checkout HEAD~1
You’ll see the warning:
Note: switching to 'HEAD~1'.
You are in 'detached HEAD' state...
3. Make a commit in the detached state
echo "experiment" >> file.txt
git commit -am "Experimental change"
HEAD now points to a new commit that’s not on any branch.
4. Inspect your state
git status
# Output: HEAD detached at <sha>
git log --oneline -3
# Output shows your new commit at the top
5. Recover: create a new branch
git branch experiment
This labels your current commit. Now HEAD still points at the commit, but you can safely switch:
git checkout experiment
# Or simply: git switch experiment
Your work is now preserved on experiment.
6. Recover: point an existing branch at it
If you prefer to fold the work into main (or any other branch), you can force-update that branch:
git branch -f main
Caution: this overwrites main — use only if you’re sure the old main is disposable. A safer alternative is to use git switch --discard-changes after noting the SHA.
7. Recover after switching away (reflog)
If you already switched back to main and your commit seems lost, find it via the reflog:
git reflog
You’ll see entries like 9c4a2d1 HEAD@{1}: checkout: moving from main to HEAD~1 and your commit’s SHA from your detached work. Then:
git branch rescue 9c4a2d1
Your work is safe again.
Compare options / when to choose what
| Method | When to use | Pros | Cons |
|---|---|---|---|
git branch <name> |
Preserve work as a new feature | Safe, explicit, no force needed | Creates a new branch you must later merge |
git branch -f <existing> |
Replace existing branch with detached work | Reuses branch name | Dangerous — overwrites history |
git checkout <branch> (no commit) |
No changes made, just exploring | Zero side effects | None |
git reflog + git branch |
Already moved away | Recovers any lost commit | Extra steps; reflog history can expire |
git cherry-pick <sha> |
Pull specific commits | Selective, no branch juggling | Requires manual conflict resolution |
Rule of thumb: If you made commits while detached, create a new branch. If you only inspected, just check out your original branch — no harm done.
Troubleshooting & edge cases
“I switched away before creating a branch — my work is gone!”
It’s not gone — it’s in the reflog. Run git reflog, find the commit SHA, then git branch to rescue it. Act quickly because reflog entries expire (default 90 days).
“I did git branch -f main and now my main is wrong!”
You overwrote main with the detached commit. To undo, find the old main SHA from the reflog: git reflog show main, then git reset --hard <sha> — or git branch -f main with the correct SHA.
“I want to discard the detached commits entirely.”
Simply git checkout main (or git switch main). Your detached commits remain in the reflog but are no longer referenced — they’ll be garbage-collected eventually. No branch needed.
“git checkout gives me ‘pathspec did not match’ errors.”
That happens when you mix commit SHAs with branch names. Ensure you’re using the full (or unique abbreviation) SHA, and avoid spaces.
“I’m stuck in detached HEAD with uncommitted changes.”
Run git stash before switching away, or use git switch --discard-changes only if you don’t need them. To keep them, git branch first.
What you learned & what's next
You now understand what a detached HEAD is, how to identify it, and several safe ways to recover from it. You learned to create a new branch to preserve your work, to force-update an existing branch, and to use the reflog to rescue lost commits — even after you’ve moved on. You can also confidently discard detached work when you’re done experimenting.
Next lesson: Now that you can rescue orphaned commits, the next step is to master refs and remotes — how branches, tags, and remote-tracking references work together, and how to manage upstreams without losing your head.
Practice recap
Create a scratch repository, check out HEAD~2 to detach, make a commit, then recover it with a new branch. Then simulate losing it by switching back to main and rescue it via the reflog. Repeat until the flow is automatic — it’s the same muscle memory you’ll use in real projects.
Common mistakes
- Switching back to a branch before creating a new branch — your detached commits aren’t lost, but they become unreferenced; use
git reflogto recover them. - Forcing an existing branch with
git branch -fwithout checking what it overwrites — you can accidentally destroy work you meant to keep. - Assuming
git checkout <commit-sha>is harmless for inspection — it’s fine for reading, but any commit you make there creates orphaned commits unless you attach a branch. - Panicking and running
git reset --hardimmediately when detached, losing uncommitted work that could have been stashed or branched first.
Variations
- Use
git switchinstead ofgit checkoutfor branch switches — it safer and more explicit when detaching. - Use
git cherry-pickto copy specific commits from a detached HEAD to your current branch without creating a new branch. - Set up a detached HEAD automatically with
git switch --detach <commit>for explicit, readable detachment.
Real-world use cases
- Inspect a bug-fix tag (e.g.,
v1.2.3) on a production checkout to reproduce a customer issue, then safely return to main without side effects. - Accidentally stumble into a detached HEAD during a code review, make a quick comment commit, and later preserve it as a suggestion branch with
git branch. - Recover an experimental commit made in detached HEAD a week ago via
git reflogand merge it into your feature branch withgit cherry-pick.
Key takeaways
- Detached HEAD means HEAD points directly at a commit, not a branch — it’s not an error, just an unlabeled location.
- Always create a new branch (
git branch <name>) before making permanent commits in a detached state. - Use
git reflogto recover any commit you think you lost after switching branches. - Use
git branch -f <existing>with extreme caution — it overwrites history. - If you make no commits while detached, simply
git checkout <branch>returns you to normal with zero side effects. - Practice detachment in a scratch repo to build muscle memory for safe recovery.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.