Comment by Certhas
If you buy the "git is just a tree of commits and pointers" mental model it's absolutely not a surprising side effect but would be the logical thing to expect. I moved a pointer to a commit around, why would that change where HEAD is pointed.
Turns out it's a tree of commits and pointers to within that tree and a master pointer that come in two versions: pointing towards the pointers or pointing towards the tree. And pointers behave very differently when the master pointer is pointing to them...
Elegant. Simple. :P
> I moved a pointer to a commit around, why would that change where HEAD is pointed.
...because HEAD points to what's checked out. This pointer does not just exist and hang around, it has its semantics. Not understanding that reveals flaws in your mental model.
Besides, the side affect you find "not surprising" here is... rewriting HEAD to change what it points to. Then you ask "why would that change where HEAD is pointed". Sounds like you may be confused. Are you forgetting that a ref may point not just to a commit, but also to another ref? This is the whole idea behind branches after all, having HEAD point to a ref is exactly what makes branches semantically different from tags - if you don't understand it then no wonder you're confused.
(protip: if you find git's "pointers to pointers" confusing, perhaps because in C a "pointer" and "pointer to pointer" are separate types that make multiple dereferencing steps explicit, think of them as symlinks instead and it should become clearer - that's in fact how symrefs used to be implemented in the past)
When a pointer is in use by higher layers, a good UI will prevent you from making direct changes underneath it unless you force it or go low-level enough for it to not matter. The only sin of git I can see here is that `git` command provides you both high-level and low-level interfaces to manipulate the data structure you're working on with no clear distinction for the user.