Checklist of fixes for a Git detached HEAD: look around, keep commits, discard commits, recover commits

Git Detached HEAD: How to Get Back to a Branch, Keep Your Commits

A detached HEAD means Git points at a commit, not a branch. Run git switch main to leave it, or git switch -c new-name first to keep your commits.

What “detached HEAD” means

Normally HEAD points at a branch name, and the branch points at a commit. In a detached HEAD state, HEAD points straight at a commit. You are not on any branch.

Git’s own glossary says the same thing: you checked out a commit that isn’t necessarily the tip of any branch. It is not an error. Git lets you look around, edit files and even commit. The only catch is that new commits have no branch name holding on to them.

How you ended up here

Checking out anything that is not a local branch detaches HEAD. According to the git-checkout manual, if the name is not a branch but is a valid commit, your HEAD becomes “detached”.

What you ran Why HEAD is detached
git checkout v2.0 A tag points at a fixed commit, not a branch.
git checkout 36d587c A commit hash is a commit, not a branch.
git checkout origin/main A remote-tracking branch is not a local branch.
git checkout HEAD~3 or git checkout main^^ You asked for an older commit by position.
git switch –detach or git checkout –detach You asked for it on purpose.
A rebase that stopped on a conflict Git replays your commits while HEAD is detached. git branch shows (no branch, rebasing topic).

How to check whether you are detached

  • git status starts with HEAD detached at v1.0 instead of On branch main. After you make commits it says HEAD detached from v1.0.
  • git branch lists * (HEAD detached at v1.0) as the current line.
  • git branch –show-current prints nothing at all. That makes it handy in scripts.

When you switch, Git also prints a long note that begins “You are in ‘detached HEAD’ state.” It repeats the two fixes below. If you find it noisy, git config advice.detachedHead false turns it off, according to the git-config manual.

Which fix do you need?

The right command depends on one question: did you make commits while detached, and do you want them?

Your situation What to run
You only looked around, no commits git switch main (or git switch – to jump back to where you were)
You made commits and want to keep them git switch -c my-new-branch
You made commits and want to throw them away git switch main. Git warns you first, but the switch still happens.
You already switched away and want the commits back git reflog, then git branch rescue <hash>
You are in the middle of a rebase Resolve the conflict and continue, or run git rebase –abort

Just looking around: go back

If you never committed, there is nothing to save. Switch to the branch you want:

git switch main

If you don’t remember the branch name, git switch – returns to the previous branch. It is the shortcut Git itself suggests in the detached HEAD note, as long as you haven’t switched around since.

You made commits and want to keep them

Give those commits a branch name while you are still detached:

git switch -c my-new-branch

This creates the branch at your current commit and moves HEAD onto it. You are no longer detached, and your commits are safe. The manual lists two more ways to attach a name: git branch foo creates the branch but leaves HEAD detached, and git tag foo creates a tag and also leaves HEAD detached.

If you want those commits on an existing branch like main, create the new branch first, switch to main, then merge the new branch into it.

You made commits and don’t want them

Just switch to a branch. In my test with Git 2.50.1, Git warned “you are leaving 2 commits behind, not connected to any of your branches”, listed both commits by hash, and then switched anyway. The warning ends with a command you can copy:

git branch <new-branch-name> e264e2e

That last line is useful even if you ignore the rest. Run it with a real name and you have your commits back.

You already switched away and lost them

The commits are not gone yet. git reflog lists where HEAD has been, newest first. This is the output from the same test:

Entry What it records
HEAD@{0}: checkout: moving from e264e2e… to main The switch that left the commits behind
e264e2e HEAD@{1}: commit: e2 Your last commit while detached
284e642 HEAD@{2}: commit: e1 Your first commit while detached
36d587c HEAD@{3}: checkout: moving from main to v1.0 The moment you detached

Find the last commit you made (here e264e2e) and point a branch at it:

git branch rescue e264e2e

The manual also shows git reflog -2 HEAD to see just the last two places HEAD pointed to. Don’t wait too long. The git-checkout manual says commits that nothing refers to will eventually be deleted by Git’s garbage collection. For reflog entries that are no longer reachable, git-reflog says the default expiry is 30 days (gc.reflogExpireUnreachable). For reachable entries it is 90 days (gc.reflogExpire).

Push and pull errors while detached

Both commands need a branch to work with, so they stop. These are the messages I got with Git 2.50.1:

Command Message
git push fatal: You are not currently on a branch. It suggests git push origin HEAD:<name-of-remote-branch>.
git pull You are not currently on a branch. followed by a request to name a branch.

The simplest fix is the one you already know. Run git switch -c my-new-branch, then git push -u origin my-new-branch. Pushing straight from HEAD works, but you end up with a remote branch and no local branch for it.

Commands that ask about the current branch, such as git branch –set-upstream-to, can’t work either. The glossary notes there is no real current branch to ask.

How to avoid detaching by accident

  • To work on a remote branch, use its short name. git switch feature does not detach. If feature doesn’t exist locally but exists on exactly one remote, Git creates a local branch from it. git checkout origin/feature is the one that detaches.
  • To inspect an old commit, use –detach on purpose. git switch –detach HEAD~3 says what you mean. If the experiment turns out well, git switch -c good-surprises keeps it, as the git-switch manual shows.
  • Uncommitted changes come along. Switching does not require a clean working tree. Git only refuses when the switch would overwrite your local changes.

Old and new commands side by side

You will see both styles in answers online. The manual lists them together.

Goal git switch git checkout
Go to a branch git switch main git checkout main
Create a branch and go to it git switch -c foo git checkout -b foo
Detach on purpose git switch –detach v2.0 git checkout –detach v2.0
Go back to the previous branch git switch – git checkout –