TL;DR: this is something of a historical accident.
Remember that git pull
means:
Run git fetch
to obtain new commits from some other Git repository. Anyone can do this safely any time so this step basically always works (unless for some reason your network is down or whatever).
Then, assuming step 1 worked, run a second Git command that messes with the current branch in some way.
Step 2 is the problematic one. The actual command run is normally git merge
; the other option is git rebase
.
Now, you can't run either git merge
or git rebase
if you have uncommitted work (with one exception that I'll leave for later). Step 1 is fine but step 2 is not, in this case.
The autostash option basically runs git stash push
for you, and git stash push
means commit what I have now, but on no branch, then do a git reset --hard
(which discards the work you did, but it's safely stored in some commits now). Having done that, step 2 is now always possible. If step 2 completes successfully—though it doesn't always, regardless of which second command you use—Git will then run git stash pop
for you.
There are a couple of reasonable questions you can ask here. One is: why not allow this before a git merge
? You can stash, rebase, and pop, but you can also stash, merge, and pop; and if you can stash, merge, and pop, why not have that as an option? The only real answer is: the --autostash
option was added to rebase back when rebase was a fancy shell script and it was easier to add it there. The merge command was not a fancy shell script and it was harder to add it there.
Another question is the one I think you did ask: if you have no commits of your own, and have done a git stash push
if needed, both git merge
—which by default does a fast-forward operation for this case, which means it does not actually merge anything—and git rebase
wind up doing the same thing: directly checking out the other Git's latest commit (and not failing in step 2 of pull). Again, one might wonder why not allow --autostash
to handle both of these cases. Again, the only real answer is "because it was easier to add to the rebase code path".
We should note that even if git merge
can do a fast-forward, it doesn't always do one. In particular, you can force Git to do a real merge instead of a fast-forward operation, using git merge --no-ff
. You can use git config
to set this up to happen on pulls (pull.ff
) or always (merge.ff
), too. So pull might do a merge even if it could have done a fast-forward instead. Still, if it can fast-forward, the merge it will do will succeed, and we're back to the same situation as before.
It's now time to mention the one special case. When git merge
can and does choose to do a fast-forward operation—essentially, a git checkout
that drags the branch name forward in the commit-graph—instead of a real merge, it's possible for Git to do this operation even if you have uncommitted work, as long as the uncommitted work is in files that are not updated by the checkout. So there's one case of a git pull
that uses git merge
that doesn't require autostash. Nonetheless, actually doing a push/fast-forward/pop sequence would be fine, and again we're really just back to the historical accident.
If you feel strongly about this sort of thing, you can always write a patch that teaches Git how to do a git pull
and/or git merge
with auto-stashing. The source for Git is available; see, e.g., the publish-only clone at https://github.com/git/git.