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".
The difference between HEAD^ (Caret) and HEAD~ (Tilde) is how they traverse history backwards from a specified starting point, in this particular case HEAD .
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.
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.
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.
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 @
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With