Git - head (lowercase) vs HEAD (uppercase)

In the command line of git you write:

HEAD is the current commit, that is the commit that is currently checkout out in the working directoy.

head, as is, means nothing for GIT, unless you have a branch or a tag named head. But that sounds like a bad idea.

But when the documentation talks about the head of a branch it refers to the last commit of that branch, maybe that is what you mean with end commit. In real commands you will use the name of the branch, such as master (or origin/master for the remote head), not the literal word head.


From what i examined, 'head' and 'HEAD' are the same, both could be used to refer to the current checked out commit.

You can checkout any commit of a branch and use git show command to examine the commit hash value.

git show head and git show HEAD will display the same commit, which is the current commit.


It's worth mentioning that when you're on a case-insensitive file system—as is the default on Windows and MacOS, for instance—that trying to open the file abc will open instead the existing file ABC, if it indeed exists, and of course vice versa.

Git stores information about the current commit in a file. For most cases, that file is named .git/HEAD. So when Git tries to access information about the current commit, it just opens .git/HEAD and reads it. (The file usually contains the name of the current branch. For instance, if you're on your master branch, your .git/HEAD file will read: ref: refs/heads/master.)

For instance, when you run git show with no addition arguments, Git reads .git/HEAD to find out that you're on master, then reads either .git/packed-refs or .git/refs/heads/master to find out which commit master means, and shows that commit. All of these are implementation details that might change in the future, and some of these do change in modern Git under some circumstances, so it's not wise to depend on this. But that's how it actually works today.

If you run git show xyz, Git tries to find .git/refs/heads/xyz and, if that doesn't work, tries to find .git/packed-refs to see if there's a line in it about branch xyz. Git also tries to find .git/refs/tags/xyz, and .git/xyz. The precise order in which Git tries each of these operations is another implementation detail, but is actually documented—after a fashion; the documentation describes the result rather than the method—in the gitrevisions manual.

If you run git show head, and you're on Windows or MacOS, Git eventually tries to open .git/head. Since your operating system is willing to treat that as a request to open, instead, .git/HEAD, and since .git/HEAD does actually exist, your OS opens .git/HEAD. Git reads ref: refs/heads/master (or whatever) out of that file, and shows you the same commit you would have seen if you had run git show HEAD or just plain git show.

Where this goes wrong, in modern Git, is when you're in an added work-tree, one constructed by running git worktree add .... The HEAD of an added work-tree is not in .git/HEAD. It's in another subdirectory of .git. If you run git show HEAD in this added work-tree, Git itself sees the special name HEAD in all-capital-letters and knows to look up the right HEAD, the one for this work-tree. But if you run git show head, Git doesn't see all-uppercase-HEAD, and goes on to try to open various files, starting with .git/head. If this succeeds—if it opens .git/HEAD—Git reads the branch for the main work-tree, and not the branch for the work-tree you're actually on in the added work-tree. So git show HEAD, in the added work-tree, shows the current commit there; but git show head, in this same added work-tree, shows the current commit of the main work-tree, rather than this one.

On Linux, using the usual file systems (which are case-sensitive), git show head just doesn't work at all. Avoid this bad habit: if you don't like typing HEAD in all uppercase, use @.

Tags:

Git