Thuta Learning
IntermediateDevOps & Toolsintermediate

HEAD and Detached HEAD

What you'll walk away with

  • Explain the core ideas behind HEAD and Detached HEAD
  • Read the diagram and trace how state or data flows through the Git/GitHub workflow
  • Decide how this applies to your own project or team

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.
text
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 here

Connect 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

bash
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
You should see
$ 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 clean

5-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

Easy traps

  • 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.
  • Always run `git status` before any destructive or history-rewriting command, to know exactly what state you're in.

Exercise

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.

You'll know it worked when: $ 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 clean

HEAD and Detached HEAD | Thuta Learning