1. Introduction

We can update our local Git repository with either git pull or git fetch. However, that’s as far as their similarities go. In this tutorial, we look into the difference between git pull and git fetch.

2. Structure of a Git Project Directory

To clearly differentiate between git fetch and git pull, a basic description of the structure of a Git project directory would help.

When we initialize a Git repository in our project directory, we split the project directory into two main components:

  • the local repository – the .git subdirectory
  • the working directory – basically, the files and subdirectories we work on

3. git fetch

git fetch updates the local repository with details of changes made in the remote repository. To do this, it writes logs, refspecs, objects, and other resources to the local repository.

Essentially, when we run git fetch in our project directory, we update only the contents of the .git subdirectory (the local repository). The working directory stays unchanged. That’s why git fetch is useful for checking changes to a remote branch without changing the working directory.

After updating the local repo with git fetch, we can run git merge to update the working directory.

3.1. Illustrating git fetch

To illustrate git fetch, we’ll push a file, file.txt, from our project directory to a remote repo:

$ cat file.txt
Hello World

In the remote main branch, we’ll edit the content of file.txt. Let’s cat the file:

$ cat file.txt
Hello Git

After updating the file in the remote branch, we’ll run git diff in our project directory. This should show the change/difference between the remote branch and the local branch:

$ git diff origin/main

Ordinarily, the command above should return an output highlighting the change we made to file.txt in the remote branch. But since we haven’t updated said change to the local repo, the command returns nothing.

Now, let’s update the remote branch’s change to the local repo with git fetch:

$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 904 bytes | 113.00 KiB/s, done.
From https://github.com/<username>/<remote-repo>
16e7ccf..1efc5e3 main -> origin/main

Next, we’ll run git diff again:

$ git diff origin/main
diff --git a/file.txt b/file.txt
index 9f4d96d..557db03 100644
--- a/file.txt
+++ b/file.txt
@@ -1 +1 @@
-Hello Git
+Hello World

Since git fetch has updated the local repo with details of the change to the remote branch, git diff now shows us that change. However, even though we’ve updated the local repo, the local copy of file.txt – a part of the working directory – will remain the same:

$ cat file.txt 
Hello World

4. git pull

Unlike git fetch, git pull updates both the local repository and the working directory with the changes made in the remote repository. In essence, running git pull is like running git fetch and git merge.

4.1. Illustrating git pull

We’ll push a file, foo.txt, to a remote repo:

$ cat foo.txt
lorem ipsum

Next, we’ll edit foo.txt in the remote main branch:

$ cat foo.txt
lorem ipsum dolor

After that, we’ll try to show the difference between the remote branch and the local branch:

$ git diff origin/main

As expected, we’ll get no output because we’ve not updated the local repo with the change to the remote branch.

Now, let’s update the change to the local repo with git pull:

$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 917 bytes | 70.00 KiB/s, done.
From https://github.com/<username>/<remote-repo>
   bf860ad..56d817d  main       -> origin/main
Updating bf860ad..56d817d
Fast-forward
 foo.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Since git pull updates both the local repo and the working directory, running git diff after git pull will still return no output:

$ git diff origin/main

Why? Well, since the content of the working directory is up-to-date with the remote branch, there would be no difference between the remote branch and the local branch.

With git fetch, only the local repo was up-to-date; the working directory was behind. Hence, there was a difference between the local branch and the remote branch.

5. Conclusion

In this article, we talked about the difference between git fetch and git pull. We demonstrated how git fetch changes only the local repo while git pull changes the whole project directory, including the local repo.