The single thing that made everything "click" together is that most things are just pointers to commits: branch names, HEAD, tags, all of them are pointers.
HEAD is pointing to the commit you're currently looking at
The name of each branch (e.g. `my-feature` points to the latest commit of that branch)
When you're on main and you `git checkout -b my-feature` then you have at least 3 pointers to the latest commit on main: `main`, `my-feature` and `HEAD`.
Every time that you make a commit on `my-branch`, then both the `HEAD` and `my-branch` move to point to the new commit.
"detached HEAD" means that the the `HEAD` (the commit you're looking at) is not pointed at by a branch.
The difference between tags and branches is that the tags point to a specific commit and do not move.
----
The other thing caught me out multiple times is that most commands seem inconsistent because git assumes default arguments:
`git checkout file.txt` is the same as `git checkout HEAD -- file.txt`
When you're on `my-branch`, `git rebase main` is the same as `git rebase main my-branch`
The difference is that the latter you can run it from other branches too.
----
Last but not least, when everything goes wrong, the single command that can take you out of any weird situation is `git reflog` which shows you all the commits that HEAD has pointed to.
Having said all that, I'm glad that git is acknowledging all this confusion and are implementing commands with fewer surprises and simpler interface as that will make it easier for newcomers to pick it up.