Why commit without a push in git?

A couple of (concrete) reasons. TLDR in bold.

The first reason is you might not be able to push to the remote, because you aren't connected to the internet.

The second reason is that sometimes commits aren't ready to be pushed. For example, I practice TDD. After I commit a failing test (which I do), I don't want to push that to the remote, because then my team may pull in a failing test suite. Another common practice is to squash these commits before pushing them out so it looks like the feature was one single commit.

Third reason is that it's a personal project that you don't want to share with anyone, and so there is no remote to push to at all. You don't have to have a remote with a git repo.

Fourth reason is you may have multiple remotes (in general, distributed semantics get in the way). So after you commit, how would git know which remote you want to push to? All of them? A certain one? A certain two out of the seven? Pushing must be explicit from git's perspective due to the semantics of git being a distributed VCS. See poke's answer for more detail.

P.S. This is off topic to the question, but the command line shells (including bash) are extremely powerful interfaces once you learn to use them. After you become proficient with these tools, using them is much faster than any GUI you're going to find. This has to do with the fact that you can do powerful actions with keystrokes instead of the mouse, and that it's infinitely customizable to fit your needs.


Git is a distributed version control system. As such, there is no single central repository, like with Subversion or even CVS. So if there was a single command to commit and push, then where would that commit would go? What would be the remote repository?

In Git, there is no central repository. There is not even any hierarchy in repositories. For a local repository, any other repository is a remote repository it can interact with. And the local repository is just a possible remote repository for any other repository.

So local and remote are just points of view relative to your current location: The local repository is always the current repository, and every other repository is a remote that you can interact with.

When working with Git, your local repository is what you interact with: You commit all your changes locally. This has many benefits and use cases that I won’t go into detail here, but essentially it is what makes version control distributed, as the local repository has all the information, the full history.

So when you have that local repository, which has the full history and all the changes, you need a way to interact with other repositories, in order to allow you to share the history. The two ways to do that are push and pull (or fetch). Since with distributed repositories, every repository is the same, every repository can push or pull from another (assuming they have access).

In the end, committing and pushing is required to be separate steps because one is interacting with the (local) repository while the other is a deliberate step to share changes with a remote repository.