References and HEAD
A Commit has an immutable Object ID. A branch name gives us a stable way to find the current tip of a line of work without memorizing that ID. Git stores that name as a reference, or ref, whose value points to a Commit.
A branch is a named reference
Section titled “A branch is a named reference”For a local branch named master, the full reference name is refs/heads/master:
reference name: refs/heads/masterreference value: <commit-id>The name is not a Commit object. After a new Commit on master, Git creates a new Commit and updates the reference value:
before: master → C3after: master → C4 → C3The old Commit C3 does not change. C4 records C3 as its parent.
HEAD identifies the current location
Section titled “HEAD identifies the current location”While working on master, HEAD is normally a symbolic reference:
HEAD → refs/heads/master → C4The .git/HEAD file can contain:
ref: refs/heads/masterMaking another Commit on master leaves that text unchanged. Git updates the value of refs/heads/master, so resolving HEAD now reaches the new Commit.
Two branches may point to the same Commit. Comparing only their Commit IDs cannot tell which branch is currently checked out; the symbolic target of HEAD can.
Inspect without changing the repository
Section titled “Inspect without changing the repository”Use read-only commands inside a disposable repository:
git symbolic-ref HEADgit rev-parse HEADgit show-ref --verify refs/heads/masterThey answer different questions:
| Command | What it reports |
|---|---|
git symbolic-ref HEAD |
The reference name currently selected by symbolic HEAD, such as refs/heads/master. |
git rev-parse HEAD |
The Object ID reached by resolving HEAD, usually the current Commit ID. |
git show-ref --verify refs/heads/master |
Whether that exact branch ref exists, followed by its Object ID and full name. |
In our training repository, the first command returned refs/heads/master; the latter two resolved to the same Commit ID shown by git log -1. On another branch, rev-parse HEAD follows that branch while show-ref --verify refs/heads/master still checks master.
Detached HEAD, as a signpost
Section titled “Detached HEAD, as a signpost”HEAD can point directly to a Commit ID instead of a branch name:
symbolic: HEAD → master → Commit Cdetached: HEAD ─────────→ Commit CIn the detached state, git rev-parse HEAD can still report the Commit ID, but git symbolic-ref HEAD cannot report a current branch. A branch elsewhere might also point to the same Commit; that does not attach HEAD to it. The practical workflow for detached HEAD belongs to a later checkpoint.
Loose and packed references
Section titled “Loose and packed references”A branch ref may exist as an individual file under .git/refs/heads/. Git can also store refs in .git/packed-refs. Therefore, the absence of .git/refs/heads/master alone does not prove that master is absent. Use git show-ref --verify refs/heads/master to ask Git whether the ref exists.
Reflogs record local ref movement
Section titled “Reflogs record local ref movement”A reflog records local updates to a reference. HEAD has a reflog, and a branch such as master can have its own reflog:
git reflog -3An entry such as HEAD@{0} is the newest recorded position of HEAD; HEAD@{1} is the preceding position. Switching branches can add an entry to the HEAD reflog without moving either branch tip. Making a Commit on the current branch updates both the branch tip and the Commit reached through HEAD, so both reflogs record the movement even though .git/HEAD still names the same branch.
git log follows Commit parent relationships. A reflog describes local reference movements, including movements that create no Commit. Reflogs are local records, not permanent backups; recovery use and retention details belong to a later checkpoint.
Common mistakes
Section titled “Common mistakes”- Treating
refs/heads/masteras the Commit ID rather than the reference name. - Assuming the text in
.git/HEADchanges after every Commit on the same branch. - Assuming equal branch tip IDs reveal which branch is checked out.
- Assuming a missing loose ref file means the branch does not exist.
- Confusing the HEAD reflog with a branch reflog or with Commit history.
Summary
Section titled “Summary”HEAD normally names the current branch ref; that ref holds a Commit ID. A Commit moves the current branch tip without changing older Commits or the symbolic text in .git/HEAD. Resolve HEAD to learn the current Commit, inspect a named ref to learn its value, and use reflogs to see local ref movement.
Knowledge check
Section titled “Knowledge check”Two branches point to one Commit. How can you tell which is current?
Inspect git symbolic-ref HEAD. Matching Commit IDs alone do not identify the checked-out branch.
What changes after a new Commit on the current branch?
The branch ref moves to the new Commit. The Commit reached through HEAD changes, so HEAD and branch reflogs record the update, while .git/HEAD keeps its symbolic branch name.