What Does "detached HEAD" mean in Git?

In git, HEAD is typically "attached" to a local branch (i.e. it points to a local branch). However, in some cases, the HEAD may be "detached" which means that whatever is checked-out locally does not point to a local branch. Such can be the case, for example, in the following instances:

When you have a detached HEAD, executing the cat .git/HEAD or git status command would show you that HEAD is pointing to a commit id/hash and not to a local branch.

When HEAD is detached, commits still work (as they normally would), however, the difference is that no named branch gets updated. It is like you're working on an anonymous branch.

Detached HEAD When Checking-Out a Specific Commit

When you checkout a specific commit, it is not connected to any local branch, and as a result, you end up with a detached HEAD. For example:

git checkout b8a076940ae86b8c5fc26dd43cd5d2aa7e95d308

This would, for example, show the following message (if you have the setting config variable advice.detachedHead set to true):

Note: switching to 'b8a076940ae86b8c5fc26dd43cd5d2aa7e95d308'.

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 b8a0769 ...

Detached HEAD When Checking-Out a Specific Tag

A tag is essentially a label to mark a specific commit in the history. Therefore, when you checkout a specific tag, (similar to checking-out a commit) it is not connected to any local branch, and as a result, you end up with a detached HEAD. For example:

git checkout tags/v1.0.0

This would, for example, show the following message (if you have the setting config variable advice.detachedHead set to true):

Note: switching to 'tags/v1.0.0'.

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 f8696ac ...

Detached HEAD When Checking-Out a Remote Branch

When you checkout a remote branch that you're not tracking (i.e. there is no local branch that is connected to the remote branch), you end up with a detached HEAD. For example:

git checkout origin/main

This would, for example, show the following message (if you have the setting config variable advice.detachedHead set to true):

Note: switching to 'origin/main'.

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 adbaa7c ...

In comparison, if you use the git switch command instead of git checkout to switch to a remote branch (without tracking it), it would fail:

git switch origin/main

fatal: a branch is expected, got remote branch 'origin/main'

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.