Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git - head (lowercase) vs HEAD (uppercase)

Tags:

git

Did I understand correct and the difference between Git head (lowercase) and Git HEAD (uppercase) is that the former is the end commit and the latter is just the current commit (whether an end-commit or a non-end commit chosen to be the HEAD commit)?

Edit: By "end-commit" I meant to "last commit of a given branch".

like image 308
pntshere Avatar asked Jan 07 '18 14:01

pntshere


People also ask

What is the difference between head and head in Git?

The difference between HEAD^ (Caret) and HEAD~ (Tilde) is how they traverse history backwards from a specified starting point, in this particular case HEAD .

What is the head in Git?

In Git, a head is a ref that points to the tip (latest commit) of a branch. You can view your repository's heads in the path . git/refs/heads/ . In this path you will find one file for each branch, and the content in each file will be the commit ID of the tip (most recent commit) of that branch.

What does Head @{ 3 refer to in Git?

git reference suffixes (^N, ~N, @{... }) ref~ is shorthand for ref~1 and means the commit's first parent. ref~2 means the commit's first parent's first parent. ref~3 means the commit's first parent's first parent's first parent.

What is head and master in Git?

The master itself is a pointer to the latest commit. The HEAD is a reference that points to the master. Every time you commit, Git updates both master and the HEAD pointers to point to the last commit by default.


1 Answers

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 @.

like image 173
torek Avatar answered Sep 30 '22 06:09

torek