Build the mental model
HEAD is Git's answer to the question 'where am I right now?' Most of the time, HEAD points to a branch name, and that branch name points to a commit — HEAD is a pointer to a pointer.
Every new commit moves the branch pointer forward, and because HEAD is attached to the branch, HEAD moves right along with it.
Detached HEAD happens when you point HEAD directly at a commit instead of a branch name — usually by running `git checkout <hash>` or `git checkout <tag>`. Nothing is broken and nothing dangerous has happened.
- Commits made while detached still get created and can still be viewed
- But no branch is pointing at them
- Switch to another branch and they become unreachable by name; Git will eventually garbage-collect them
- To keep them, create a branch right there with `git switch -c <new-branch-name>`
Getting back to normal is simple — just check out a branch name again, like `git checkout main`, and HEAD reattaches to it.
- HEAD
- A pointer to whatever commit you currently have checked out — normally reached indirectly through a branch name.
- Detached HEAD
- The state where HEAD points directly at a commit instead of at a branch name, usually after checking out a specific commit or tag.
HEAD: NORMAL VS DETACHED
------------------------
HEAD: NORMAL VS DETACHED
--------------------------
Normal (attached):
HEAD --> main --> commit C3
|
commit C2
|
commit C1
Detached:
HEAD --------------> commit C1 (no branch name in between)
|
commit C2
|
commit C3 <- main still points hereConnect it to a real scenario
Detached HEAD often happens by accident — checking out a commit hash to inspect old code, or checking out a tag.
Git tells you plainly: `git status` shows 'HEAD detached at <hash>' instead of the usual 'On branch main'. That message is a cue, not a warning of damage.
Just looking around
Nothing to clean up — just check out your branch again.
Reattach
`git checkout main` (or `git switch main`) reattaches HEAD and prints 'Switched to branch main'.
Made commits while detached?
Create a branch before switching away: `git switch -c fix-from-old-version`. Otherwise those commits become unreachable.
Not an error — a normal state
Detached HEAD looks alarming the first time you see it, but nothing is broken. You can look around, run code, even make experimental commits. The only fix you ever need is checking out a branch name again.
Try the working example
git init -q -b main
git config user.name "Thuta Learner"
git config user.email "learner@example.com"
git init -q -b main
git config user.name "Thuta Learner"
git config user.email "learner@example.com"
export GIT_AUTHOR_NAME="Thuta Learner"
export GIT_AUTHOR_EMAIL="learner@example.com"
export GIT_COMMITTER_NAME="Thuta Learner"
export GIT_COMMITTER_EMAIL="learner@example.com"
echo "line1" > notes.txt
git add notes.txt
GIT_AUTHOR_DATE="2026-01-03T09:00:00" GIT_COMMITTER_DATE="2026-01-03T09:00:00" git commit -m "Add notes"
FIRST_COMMIT=$(git rev-parse HEAD)
echo "line2" >> notes.txt
git add notes.txt
GIT_AUTHOR_DATE="2026-01-03T10:00:00" GIT_COMMITTER_DATE="2026-01-03T10:00:00" git commit -m "Update notes"
git log --oneline
git checkout $FIRST_COMMIT
git status
git checkout main
git status$ git log --oneline
301b387 Update notes
aec746a Add notes
$ git checkout aec746a
Note: switching to 'aec746a'.
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.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at aec746a Add notes
$ git status
HEAD detached at aec746a
nothing to commit, working tree clean
$ git checkout main
Previous HEAD position was aec746a Add notes
Switched to branch 'main'
$ git status
On branch main
nothing to commit, working tree clean5-minute try-it
In a repo with at least two commits, checkout the first commit by its hash to deliberately detach HEAD. Run `git status` and read the message Git gives you. Then check out your branch again and confirm `git status` returns to normal. Finally, try making one commit while detached, switch to a branch, and observe (with `git log`) that the branch doesn't include that commit.
One important caution
Making commits in detached HEAD and then switching branches without creating a branch first can leave those commits unreachable and eventually garbage-collected.
Seeing 'detached HEAD' in `git status` is not itself a problem — panicking and force-resetting things can lose work that a simple `git switch -c` would have saved.
Git Documentation: git-checkout (detached HEAD) — Git & GitHub