Git detached HEAD: recover lost commits fast
You checked out a commit hash and lost your work. Here's how to get those commits back with a branch, then why it happens.
You're in detached HEAD and your commits feel gone. I've been there.
Here's the quick fix: run git reflog to find those commits, then create a branch from them. Don't panic — they're still there.
The fix in two commands
- Open your terminal in the repo.
- Run
git reflog. You'll see a list of every HEAD move, including your detached commits. Look for the ones you made. They'll be near the top, usually with messages like "commit: your message here". - Pick the commit hash (first 7 characters, e.g.,
abc1234) that's the latest one you want to keep. - Run
git checkout -b recovered-branch abc1234. This creates a new branch namedrecovered-branchpointing to that commit. You're now attached again, with all your work. - If you had a series of commits, pick the most recent one. Git will pull in the whole chain.
That's it. You're done. Your commits are safe on a real branch now. Push them with git push origin recovered-branch if you need to share them.
Why this works
Detached HEAD means your HEAD pointer is on a commit, not a branch reference. When you commit while detached, those commits exist — git tracks them in its object database — but no branch points to them. They're orphans. A normal git checkout main moves HEAD away, and without a branch, those commits seem lost.
The git reflog is your safety net. It records every time HEAD moves, including checkouts, commits, rebases, and resets. It's a local log that lives in .git/logs/HEAD. It doesn't get pushed to remotes. That's why git reflog saved you — it tracks the history of your HEAD movements, not just branch tips.
Creating a branch with git checkout -b points a named branch reference at that commit. Now git log shows it, git push sends it, and future checkouts don't lose it.
What if git reflog doesn't show your commits?
This is rare but can happen if you ran git gc (garbage collection) or if the reflog expired. Git keeps reflog entries for 90 days by default (configurable with gc.reflogExpire). If you're past that, you're in a tougher spot.
Option A: Look at git fsck
Run git fsck --lost-found. This searches the object database for dangling commits — commits not reachable from any branch or tag. It'll spit out hashes. You can inspect them with git show <hash> and then branch them the same way.
Option B: Check your stash
If you stashed before detaching, run git stash list. You can apply a stash with git stash pop. But stashes are branches under the hood, so they don't cause detached HEAD issues themselves.
Option C: You might have already created a branch
Sometimes people detach, commit, then create a branch but forget. Run git branch -a to list all branches. If you named one earlier, you're fine.
Common scenario: accidental checkout of a tag
This one trips people up constantly. You run git checkout v1.0 thinking you're switching to a branch, but v1.0 is a tag. Tags are immutable — you can't commit to them. Git puts you in detached HEAD. You make changes, commit, then later do git checkout main. Poof — those commits are orphaned until you run git reflog.
Fix is the same: git reflog, find the commit, branch it.
How to avoid this in the future
- Always create a branch before making changes. If you checkout a hash or a tag, run
git checkout -b my-workimmediately. This attaches HEAD to a new branch. - Use
git switchinstead ofgit checkout. Git 2.23+ introducedgit switchfor branch operations andgit restorefor file operations.git switchwill refuse to detach you unless you usegit switch --detach. It's safer. - Configure your git to warn you. Set
advice.detachedHeadto false if you hate warnings, but keep it true (default) — it reminds you what you're doing. - Commit early, commit often. If you commit while detached, you have a trail to recover. Uncommitted changes in detached HEAD are harder — you'd need
git stashor manual re-creation.
Real-world trigger: updating a hotfix branch
Say you're on main and need to cherry-pick a commit from a feature branch. You run git checkout abc1234 (the commit hash). You fix a conflict, commit. Now you're detached. Later, you git checkout main. You lost that fix. Reflog to the rescue — or better, you could have run git cherry-pick abc1234 directly on main and avoided detaching entirely.
"Detached HEAD is not a crisis. It's a sign you forgot to name your branch." — every senior dev who's fixed this a dozen times.
If you're reading this after panicking: take a breath. Run git reflog right now. Your commits are probably there. You'll have this fixed in under a minute. After that, consider adding a shell alias like git save-me='git reflog | head -20' — might save you next time.
Was this solution helpful?