(Maybe this is a comment, but it is too large and needs good formatting :-) ... Also, I seem to be freaky if you follow some links ...)
The key to understanding this is, I think, you are already there, but let me put this in an SO article to make the reader understand the following:
All git refs complete the naming (pointing) to a single commit.
This is true for tags (whether light or annotated), branches, "deleted branches", git "marks" links, "wallet", etc. They all call one commit and what it is. (Well, fine, not really: technically, tags can name any object in a repo. Actually, how annotated tags work: there is a light tag that names a repository object, which is an annotated tag, and then the annotated tag names a commit object. Also how HEAD works: it usually calls another ref, which then calls commit. So sometimes you need to peel a few layers of a bow to press a commit. Naming a blob or tree object is possible, but usually it does nothing.)
(The "true name" of the commit is, of course, the SHA-1 value.)
What makes the link name for the "special" branch equally simple:
A branch link is a name that automatically moves to a new branch tip when new commits are added.
In particular, a ref of the form refs/heads/branchname indicates some commit (by definition, since the names indicate a commit). When you are "on", this is branch 1 and do some git operation that adds a new commit, like git commit or git merge or git cherry-pick , git commits the new commit to the repo, then re-points the name to the new commit. That is all there is to it!
What we call a "branch" is formed starting from the top - a commit that this name points to and working backwards using each parent, or parents. If the commit has one parent, this is the usual commit on a branch. If he has two or more, this is a “merger,” and you can follow all your parents to find what has merged. If he has no parents at all, this is a root commit (for example, the initial commit in a new repo - in fact you can have more than one root; git "notes" do this, for example).
If you put seven shortcuts on one commit, now you have seven 2 names for the "branch". If you clear this down to one, it will be less confusing , of course, but git is all the same. (Git only cares if you take it to zero names. Now the branch still exists, but it is very difficult to find, and it has the right to garbage collection .)
Since we are discussing this topic, let's also take a note on " remote branches." (I was never happy with the name "remote branch", but I have no better one, so let's just define it.) "Remote branch" is a local link to the form refs/remotes/rname/ bname , where rname is the name of the console (for example , origin ), and the name bname is the name of the branch on the remote control, that is, the part that appears after refs/heads/ if you go to this remote and look at the branch there. You cannot get the remote branch “on” - if you git checkout origin/master , git provided a “stand-alone HEAD” , but these branch names are automatically updated: when you use git fetch to get new commits from the remote, you also get new tips branches. In other words, instead of moving names to new branch hints, you let someone else do it (on the remote control), and then you get your latest version right away when you extract from them.
1 To be "on a branch", the HEAD ref link must be an "indirect" link, something like ref: refs/heads/master . When HEAD "disconnected" instead, it contains the raw SHA-1 value. You can add commits; they are added to the unlabeled branch. The link in HEAD does not allow garbage collection.
2 Or more if there are tags. Suppose there are no tags .
3 No third footnote.