Reputation: 99418
HEAD
is a symref of the current branch.
I thought it is implemented as a file ref/heads/HEAD
(just like master
is implemented as ref/heads/master
), but there is no such a file.
Is HEAD
implemented as a file?
Upvotes: 0
Views: 150
Reputation: 96
HEAD file is at the root (search for .git/HEAD) and its content is a "pointer -> to a reference -> of the commit", at the tip of the current branch.
On branch master:
$ cat .git/HEAD
ref: refs/heads/master
On branch issue_99:
$ cat .git/HEAD
ref: refs/heads/issue_99
As you can see, HEAD contains a pointer to another reference. You can get this value also with:
$ git symbolic-ref HEAD
refs/heads/issue_99
If you look inside the destination reference, you get the SHA-1 value:
$ cat .git/refs/heads/issue_99
92fff2a187ff1a35fa8a721c31465fad289998bb
When you commit an object, it belongs to the branch you're on (issue_99), and that branch is fingerprinted with the SHA-1 you see here.
In simple words, HEAD means "current branch", defining a pointer to a reference. When you checkout, you just update that pointer.
See: git reference
For better understanding, look inside .git/refs: it contains references to commit object hashes, in a human-readable format. So, inside this dir, you find branches, remotes and tags. In my case:
$ ls -F .git/refs/
heads/ remotes/ tags/
Note that heads contains files named as my local branches, in repository.
In our example:
$ ls .git/refs/heads/
issue_99 master
They contain the commit hash you usually see:
git log -1 issue_99
commit 92fff2a187ff1a35fa8a721c31465fad289998bb
Author: deeper-x <[email protected]>
Date: Mon Jan 7 10:46:13 2019 +0100
fancy description of fooBar commit
Coming back to our .git/HEAD file, you see why is considered a "special" reference: it symbolically references to the tip of the current branch (to a "ref", inside the refs/ container).
Now you understand why, for example, when you want to remove a file from stage (unstage), mantaining modifications, you use:
git reset HEAD myFooBar.c
It's easy to understand what's happening: HEAD is the last commit of the current branch, and you're just resetting it, w/o touching the file.
Upvotes: 3