When you checkout (now switch) a branch, HEAD is now the same as the branch (they point to the same commit). When you do operation like commit, reset, reset,... both the head and the branch are updated. So if a remote node tries to update the local node via a push on its end, that would mess up the local worktree. So you create a bare repo instead which can't contain a local worktree.
Note: A worktree is computed from the initial commit to the commit currently identified by HEAD by following the parent information on each commit.
The staging area is like a stored snapshot of what you would like to commit. You can always create patch between HEAD and the worktree, edit it, and then save the patch as the commit, then apply the leftover to the worktree. The staging just make that easier. It's a WIP patch for the next commit.
Actually, HEAD now points to that branch, which in turn points to the commit. It's a different state than when HEAD points directly to the same commit (called "detached HEAD" in Git's terminology) where this issue doesn't happen as you're not on a branch at all. It's a subtle, but important distinction when trying to understand what happens under the hood there.
You can push to a repo with a working copy, if you like; nothing will happen to that working copy unless you run `hg update`. Since you don’t need a working copy on the server’s repo, you never run `hg update` on it, and it’s effectively what git calls a bare repository.
Case one: WiP on a branch, code is pretty stable, but I want to do some experiments which will likely be deleted. I stage everything and then make (unstaged) changes which I can then undo with two keystrokes.
Case two: I'm reviewing a complex PR, so I first merge it with --no-commit, then unstage everything and then stage chunks (or even individual lines) I have already reviewed.
Case three: I was coding in the state of flow and now I have a lot of changes I want to commit, but I want to separate them into several atomic commits. I stage the first batch of changes, commit, then stage another, commit, etc.
There are probably more, but these three alone are worth having the staging area.
Case two: you don't need staging. You can stash, and then unstash incrementally (I would be shocked if git doesn't have the equivalent of `hg unshelve --interactive` and its keyboard friendly TUI)
Case three: you don't need staging. You can just edit/amend the series (rebase --interactive I believe you guys call that).
That is to say, all that you want to put in your stash, you could commit directly to the DAG, and edit to your convenience, with the regular history-rewriting tools already at your disposal. And the off-DAG stuff can be handled by stash (and even there, a normal commit that you would rebase to its destination would perfectly do).
And what I described is incidentally what https://github.com/jj-vcs/jj does, which can be pretty-well described as "taking the best of all major VCSes"
The immediate response from many git users when confronted to alternative VCSes is "well, it doesn't have a staging area, so it's obviously inferior" instead of going with "let's see how differently they approach this problem, and perhaps I will like it/git isn't all perfect after all".