Tim
Tim

Reputation: 99418

Is `HEAD` implemented as a file?

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

Answers (1)

Alberto de Prezzo
Alberto de Prezzo

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

Related Questions