By admin , 28 April 2026

Introduction

HEAD is the most important reference in Git. It tells Git which commit your next commit will descend from. Most of the time HEAD points at a branch, and that branch points at a commit; but HEAD can also point directly at a commit (detached HEAD).

Where it lives

HEAD is a single file at .git/HEAD. Inspect it:

cat .git/HEAD
# ref: refs/heads/main

That single line says "HEAD currently points at the branch main". When you commit, Git advances main and HEAD follows.

Inspecting HEAD

git rev-parse HEAD              # commit SHA
git symbolic-ref HEAD           # underlying ref name
git log -1 HEAD --oneline

Detached HEAD

Checking out a commit, tag, or remote-tracking branch directly puts HEAD in detached state:

git checkout v1.2.3
# You are in 'detached HEAD' state.

.git/HEAD now contains a raw SHA. New commits go nowhere except into the reflog; switch back to a real branch (or create one) before you lose them:

git switch -c experiment

HEAD shorthands

  • HEAD: the current commit.
  • HEAD^ or HEAD~1: parent.
  • HEAD~3: three commits back via first parent.
  • HEAD^2: second parent of a merge commit.
  • HEAD@{1}: previous position from the reflog.
git log HEAD~5..HEAD --oneline
git diff HEAD^ HEAD

Other special HEADs

  • ORIG_HEAD: previous HEAD before a "dangerous" operation (merge, reset).
  • MERGE_HEAD: tip of the branch being merged.
  • FETCH_HEAD: tip of whatever was just fetched.
  • CHERRY_PICK_HEAD: commit being cherry-picked.

HEAD in scripts

Scripts often need to know the current branch name. Use plumbing rather than parsing porcelain output:

branch=$(git symbolic-ref --short -q HEAD) || branch="(detached)"
sha=$(git rev-parse HEAD)
short=$(git rev-parse --short HEAD)

symbolic-ref --short -q HEAD exits non-zero in detached state, which makes it a perfect detector. git branch --show-current (Git 2.22+) is a friendlier alternative that prints empty output when detached. Both are stable across versions; git status output is not.

HEAD and worktrees

Linked worktrees each have their own HEAD. The main repository's .git/HEAD is one of many; each worktree has its own under .git/worktrees/<name>/HEAD. This means two worktrees of the same repository can be on different branches simultaneously:

git worktree add ../wt-feature feature/login
git -C ../wt-feature rev-parse HEAD
git -C . rev-parse HEAD

The two HEADs are independent. Branch checkout is exclusive across worktrees: a branch can only be checked out in one worktree at a time, preventing accidental concurrent edits to the same branch from two locations.

Common mistakes

Believing that HEAD is a synonym for "current branch". It is not; it is a pointer that usually points at one. Treating HEAD~3 and HEAD^3 as equivalent: they differ on merge commits. Editing .git/HEAD by hand to switch branches; use git switch or git checkout instead. And finally, ignoring "detached HEAD" warnings and committing into the void; if you find yourself there with new commits, do git switch -c <newbranch> immediately to anchor them.