When Git says HEAD is now at 2eb4807... You are in 'detached HEAD' state, it means HEAD is pointing directly at a commit instead of at a branch name. Nothing is broken. The fastest fix is git checkout main (or master) to reattach HEAD to your branch, or git switch - to return to wherever you just came from. If you made commits in this state that you want to keep, run git switch -c new-branch-name first to save them.
What "detached HEAD" actually means
Normally, HEAD is a pointer to a branch name, and that branch name points to the latest commit. When you're on main, the file .git/HEAD contains:
ref: refs/heads/main
In detached HEAD state, Git skips the branch reference entirely and points HEAD straight at a commit SHA:
2eb4807026d2fa8a61a8ea97c781a104ab750e09
That's it. HEAD is "detached" from any branch. Commits you make here are real and fully functional β they're just not reachable via any branch name, so they become hard to find later and are eventually cleaned up by Git's garbage collector.
The three common causes
1. Checking out a specific commit SHA
$ git checkout 2eb4807
Note: switching to '2eb4807'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
HEAD is now at 2eb4807 first commit
You typed a commit hash (or pasted it from git log) instead of a branch name. Git has no choice but to detach HEAD since there is no branch to point to.
2. Checking out a tag
$ git checkout v1.0
Note: switching to 'v1.0'.
You are in 'detached HEAD' state.
HEAD is now at ea0bc5e second commit
HEAD detached at v1.0
Tags are fixed pointers to commits, not branches. Checking one out always detaches HEAD. This catches people who want to "look at the v1.0 code" and then accidentally start editing.
3. Checking out a remote-tracking branch directly
$ git checkout origin/main
HEAD is now at 7f5c08d third commit
HEAD detached at origin/main
origin/main is a snapshot of what the remote looked like last time you fetched, not a local branch. To actually work on it, you want git checkout main or git switch main.
Fix 1: You haven't made any commits β just go back
If you entered detached HEAD just to look around and haven't committed anything, go back to your branch:
$ git checkout main
Previous HEAD position was 2eb4807 first commit
Switched to branch 'main'
On branch main
nothing to commit, working tree clean
Or use the shorthand git switch - to return to whichever branch you were on before:
$ git switch -
Previous HEAD position was ea0bc5e second commit
Switched to branch 'main'
The - argument means "previous location", like cd - in bash.
Fix 2: You made commits in detached HEAD and want to keep them
This is where people panic. You were exploring, got excited, made two commits, and now you need to save them before switching branches. Do not switch branches yet β do this first:
$ git switch -c my-experiment
Switched to a new branch 'my-experiment'
That's the entire fix. git switch -c <name> creates a new branch pointing at the current commit and attaches HEAD to it. Your commits are now safe. You can verify:
$ git log --oneline
60028dc experimental commit
2eb4807 first commit
If you want to merge those commits back to main:
$ git checkout main
$ git merge my-experiment
Fix 3: You made commits but want to discard them
If you were experimenting and don't want the commits, just switch away. Git will warn you if there are unsaved changes, but committed work in detached HEAD is not deleted immediately β it sits as a dangling commit until the next git gc. You can still recover it with git reflog within a few weeks if you change your mind.
$ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
60028dc experimental commit
If you want to keep it by creating a new branch, this may be a good time
to do so with:
git branch <new-branch-name> 60028dc
Switched to branch 'main'
Git itself reminds you of the SHA in case you change your mind.
Recovering commits you already left behind
If you switched away and lost the SHA, git reflog lists every position HEAD has been in, in reverse chronological order:
$ git reflog
7f5c08d HEAD@{0}: checkout: moving from 60028dc to main
60028dc HEAD@{1}: commit: experimental commit
2eb4807 HEAD@{2}: checkout: moving from main to 2eb4807
...
Find the SHA you want (here 60028dc) and create a branch from it:
$ git branch recovered-work 60028dc
$ git checkout recovered-work
The modern way: git switch
Git 2.23 introduced git switch and git restore to split the overloaded git checkout command. For detached HEAD work, the relevant commands are:
# Explicitly enter detached HEAD (clear intent)
$ git switch --detach v1.0
HEAD is now at ea0bc5e second commit
# Create branch and attach HEAD in one step
$ git switch -c new-feature
# Return to previous branch
$ git switch -
Using git switch instead of git checkout makes it harder to accidentally enter detached HEAD because git switch requires the explicit --detach flag to do it intentionally.
Quick reference
| Situation | Command |
|---|---|
| No commits made, go back to branch | git checkout main or git switch - |
| Made commits, want to save them | git switch -c new-branch |
| Made commits, want to discard them | git checkout main (Git warns you) |
| Already lost the SHA | git reflog, then git branch name <sha> |
| Check out tag without detaching | Not possible β always creates a branch first |
Tested on Ubuntu 24.04 with git version 2.43.0.