Git: Difference Between 'git fetch' and 'git pull'

As a beginner programmer, or even for many experienced programmers, Git version control can be difficult to learn and master. Much of the reason, in my opinion, is due to the many different commands that exist and the small differences between them.

One such example is the difference between git fetch and git pull. At first glance the name of the commands don't give much hint as to how they differ, so in this article I'll be explaining the difference between the git fetch and git pull commands.

Git Fetch

The fetch command retrieves any commits, references (like tags), branches and files from a remote repository, along with any other corresponding objects. However, not all tags are retrieved as this command only takes the ones that point to commits that you are retrieving. Basically this command fetches anything needed to reconstruct the history of the particular branch you're interested in.

The basic syntax is the following:

$ git fetch <remote-repo> <remote-branch>

Specifying <remote-branch> will only fetch changes from that branch. If this parameter is omitted then changes from all branches are retrieved.

The interesting thing about the fetch command is that it doesn't actually affect anything in your local repo. No working changes will be lost, and you'll see no direct affect on your local branches. This is because Git keeps fetched content separate from your own repo's content until it is merged in.

So, let's say you want to view changes for the "master" branch from the "origin" remote repo before deciding to merge them in to your repo. To do this you could use the following commands:

$ git fetch origin master

Now that you have the changes in your repository, you'll likely want to actually view them, which you can do by just checking out the branch:

$ git checkout origin/master

This will allow you to see the changes, and it still isn't merged in to any of your own branches.

A quicker way to view these changes would be to just look at the commit logs, which you can do with:

$ git log master..origin/master

Note that this is considered a "safer" method than pull since it does not actually make any changes to your local branches.

Now that we've seen what fetch does and a bit about how it works, let's take a look at pull.

Git Pull

The git pull command is what I'd call a "high level" command. By that I mean that it performs the actions of a few other Git commands in sequence, which I'll explain more about below. In this section, after I describe the difference between fetch and pull, I'll also briefly talk about the numerous different ways the command can be used.

The general syntax is the following:

$ git pull <remote-repo> <remote-branch>

Both the <remote-repo> and <remote-branch> parameters are optional, as long as your current branch is tracking a remote one.

Probably the simplest way to explain this command, and how it's different from fetch, is that it's an alias for two other Git commands, when used in its default mode: fetch and merge. So by running git pull you are essentially running these two commands in sequence:

$ git fetch <remote-repo>
$ git merge FETCH_HEAD

Here FETCH_HEAD is a reference to tip of the last fetch, which is being merged in to your current branch.

So obviously the big difference between fetch and pull is that pull actually performs a fetch in addition to a merge.

Although depending on the option you give to git pull, it may work differently than this. For example, if you add the --rebase option then it will instead use git rebase instead of git merge.

There is also the --no-commit option, which will perform the merge command, but will (as stated in the official documentation) "pretend the merge failed" and not autocommit it. This allows you to take a look at the changes you just fetched before actually committing it to your code.

There are quite a few more options available, most of which are beyond the scope of this article. I'd recommend taking a look at the official documentation for more info.