I'm a huge fan of git (but became one the hard way) and I think that most of the poor design decisions are in the command layer. Largely the tendency for the same command to do several things that, to the user, are wildly different (often because they map to the same fundamental operation on the DAG).
As the most simple example, git add both adds a new file to the index and adds changes to an existing file to the index. They are both fundamentally the same operation, but your intentions are different.
Checkout, likewise, both changes HEAD's symbolic reference and changes the working copy to match the index or a commit. This makes it both a means of full tree changes and local reversion.
And then there's rebase...
I don't think these are huge issues, but I do think they're barriers and a source of common early issues with git for new users.
This is exactly what I was getting at. git's command layer is much like the "new" keyword in Javascript -- it's a false abstraction of a relatively elegant underlying system [1]. As it is, the command layer encourages a naive mental model that is both inaccurate and leaky. You end up having to learn both the abstraction layer and the actual system underneath in order to actually understand what any of the commands do.
[1] I assume this was originally done to make git seem more approachable to SVN or CVS users.
I find that SVN users have the most trouble with git, so I don't think that's true. Mercurial has a similar underlying model but has a porcelain layer that svn users find far more comfortable.
The branch switching behaviour definitely seems taken from cvs, but somehow works much much better than it ever did in cvs.
I assume you're referring to the use of the different flags?
For the latter two, no disagreement there. For the former two, there is a difference between returning a verbose response within the context queried and expanding the inclusive parameters of the query. 'git remote -a' makes no sense as all remotes are equivalent (there is no such thing as a local remote).
If you're curious, "git remote", "git branch", and "git tag" all present a list without supplying those options. You only need "git branch -a" if you want to see remote branches.
"git stash" is certainly the outlier; the reason is that when "git stash" was first added it was meant to be a short-and-sweet command. Otherwise, you'd be forced to type "git stash save <name>", which is not so short and sweet. "git stash list" was added later.
I agree the CLI can be a pain, but it's slowly improving. It's in a better state now than it was a few years ago. For example
git push origin :topic-branch
can now be replaced with
git push origin --delete topic-branch
This still has issues, there's now multiple ways to do the same thing. There's also different commands (git push vs git branch) for the same action, deleting a branch (regardless if it is remote or local).
As the most simple example, git add both adds a new file to the index and adds changes to an existing file to the index. They are both fundamentally the same operation, but your intentions are different.
Checkout, likewise, both changes HEAD's symbolic reference and changes the working copy to match the index or a commit. This makes it both a means of full tree changes and local reversion.
And then there's rebase...
I don't think these are huge issues, but I do think they're barriers and a source of common early issues with git for new users.