git fetch vs git pull Explained [With Examples]


Written by - Deepak Prasad

 

Introduction to git fetch vs git pull

In this tutorial git fetch vs git pull, we will learn and compare how the two work in a remote and local repository.

 

Git fetch

A git fetch function downloads the most recent changes in a shared remote repository after the last fetch. Understand that the git fetch operator does not engage in any file transfer but serves to check any recent changes in the remote.

 

Git pull

A git pull function transfers and merge the upstream metadata into the local active repository.

git pull = git fetch + git merge

To update the latest remote changes to your active local repository git fetch function is the most recommended. That’s because the fetch function will not automatically merge those updates into your local codes like what git pull does. Fetched contents are kept separate from your current local commit until you decide to merge them.

Only consider git pull when you are sure you have a clean copy to update remote changes to your local active copy.

 

git fetch vs git pull visual comparison

The diagram below illustrates the comparison between git fetch vs git pull functions.

git fetch vs git pull Explained [With Examples]

 

git fetch vs git pull workflow

Here is a basic command workflow which will you give you a high level idea of git fetch vs git pull in real time scenario:

 

git fetch workflow

## checkout to your branch
git checkout mybranch

## fetch the changes
git fetch

## check the difference compared to origin
git diff origin/mybranch

## perform rebase
git rebase

 

git pull workflow

## checkout to your branch
git checkout mybranch

## pull the changes
## This perform fetch + merge
git pull

 

A comparison table for git fetch vs git pull function

Below is a table that displays the comparison between the git fetch function vs git pull function:

git fetch git pull
Syntax: git fetch <remote> Syntax: git pull <remote-branch>
It updates all the changes from the remote repo to the local one without merging them It fetches and integrates the remote changes
Keeps checks for any updates from the remote Update the remote changes by directly merging them into the local repo
Uses the checkout command to merge the remote changes into local repository does not need the checkout command to merge the changes into local as its an automatic process of fetch and merge
It is a safe approach for getting remote data as there is no room for conflicts It has high possibilities of creating conflicts especially when two developers are working on the same branch and perform pull
It gives you the autonomy to merge the remote changes to your local repo as per your preferences The process is automatic and you have no room for making further adjustment once you perform git pull
Updates you about the work done by other developers on a collaborated project Updates and merges the work from other developers into your local repository

 

Example-1: Using git fetch vs git pull to get new branch from remote repository

How git fetch works

Assuming we have a repository git_pull which is used by multiple developers. Now these developers create different branch, every time they are working on some development or testing activity.

For example user deepak and alisha have cloned this project and user alisha has created a new branch in her local workstation.

alisha@ubuntu:~/git_pull$ git branch
* main

alisha@ubuntu:~/git_pull$ git checkout -b dev
Switched to a new branch 'dev'

alisha@ubuntu:~/git_pull$ git branch
* dev
  main

Next alisha performs some work with commit id e27f9a2 and then pushes her changes to remote repository:

alisha@ubuntu:~/git_pull$ git push origin dev

alisha@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

Now user deepak performs git fetch to get all the refs, tags and branched from remote repository to his local repo:

deepak@ubuntu:~/git_pull$ git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 293 bytes | 293.00 KiB/s, done.
From gitlab.com:golinuxcloud/git_pull
 * [new branch]      dev        -> origin/dev

From the output you can see, a new branch dev has also been fetched.

Verify the available branches:

deepak@ubuntu:~/git_pull$ git branch -a

Sample Output:
git fetch vs git pull Explained [With Examples]

Check if all the commits from alisha are also fetched:

deepak@ubuntu:~/git_pull$ git checkout dev

deepak@ubuntu:~/git_pull$ git branch

deepak@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

So, looks like with git fetch, all the commits from alisha were also fetched and merged into the dev branch. This is because git fetch has actually fetched all the available branch from remote repository along with the changes in those branch

 

How git pull works

Next we use git pull to verify the same activity. User alisha creates another branch i.e. prod and pushes some of her changes to remote repository into this new branch:

alisha@ubuntu:~/git_pull$ git checkout -b prod
Switched to a new branch 'prod'

alisha@ubuntu:~/git_pull$ git branch
  dev
  main
* prod

alisha@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

So based on this output, alisha has added a new commit 83eccc0 into the prod branch.

Next deepak performs git pull this time to get all the latest changes from remote repository. The output looks pretty much the same as git fetch as this also indicates a new branch being pulled.

deepak@ubuntu:~/git_pull$ git pull
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 255 bytes | 18.00 KiB/s, done.
From gitlab.com:golinuxcloud/git_pull
 * [new branch]      prod       -> origin/prod
Already up to date.

List the available branch, here you can see now we have a new prod remote branch:

deepak@ubuntu:~/git_pull$ git branch -a

Sample Output:
git fetch vs git pull Explained [With Examples]

Verify the changes from alisha user inside the prod branch:

deepak@ubuntu:~/git_pull$ git checkout prod

deepak@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

As you can see, the commit id 83eccc0 from alisha has also been pulled.

 

Conclusion

In this example we don't see any difference between git fetch and git pull as both the commands were able to get all the changes from remote repositories which were committed inside a different branch compared to the local branch where the pull or fetch operation was performed.

So we can conclude that when you are performing git fetch or git pull for a different branch (not your current branch) then all the changes are fetched/pulled and merged into that respective branch.

 

Example-2: Using git fetch + git rebase vs git pull (on same branch)

In this section we will demonstrate the usage of git fetch vs git pull while working on the same branch. We have a project with 2 developers, deepak and alisha. Both of them have cloned the repo's (git_pull) main branch.

 

How git fetch works?

Now alisha already starts working on this project and she commits a new file and pushes the same to remote repo. As you can see, currently she is working on the main branch and has committed alisha_file into the remote repo with commit id 8e954f8

alisha@ubuntu:~/git_pull$ git branch
* main

alisha@ubuntu:~/git_pull$ git log --oneline
8e954f8 (HEAD -> main, origin/main, origin/HEAD) alisha's first file
cf2e9eb Initial commit

Next deepak decides to fetch the changes before starting with his assigned tasks.

deepak@ubuntu:~/git_pull$ git log --oneline
cf2e9eb (HEAD -> main, origin/main, origin/HEAD) Initial commit

deepak@ubuntu:~/git_pull$ git branch
* main

Next deepak performs a git fetch operation. From the fetch output you can see that reference of commit id 8e954f8 has been fetched successfully from the remote repository:

deepak@ubuntu:~/git_pull$ git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 257 bytes | 257.00 KiB/s, done.
From gitlab.com:golinuxcloud/git_pull
   cf2e9eb..8e954f8  main       -> origin/main

Next we check the commit history, but the commit id 8e954f8 entry is missing here. This is how git fetch works. It fetches all references of all the commits from the remote repository, but it does not merge them automatically. So this gives you a window to check the differences and make any changes to avoid any merge conflict.

deepak@ubuntu:~/git_pull$ git log --oneline
cf2e9eb (HEAD -> main) Initial commit

Compare the differences between local and remote repository. As highlighted, we have a new commit on remote repository for alisha_file which is not available locally.

deepak@ubuntu:~/git_pull$ git diff origin/main
diff --git a/alisha_file b/alisha_file
deleted file mode 100644
index e69de29..0000000

Once we know there are no impacts of the merge, we will perform a rebase to merge all the changes into our local branch:

deepak@ubuntu:~/git_pull$ git rebase origin/main
Successfully rebased and updated refs/heads/main.

Check if there are any more missing changes (we get a blank output):

deepak@ubuntu:~/git_pull$ git diff origin/main

Re-verify the commit history and now you can see the commit id from alisha which she did while working on this project.

deepak@ubuntu:~/git_pull$ git log --oneline
8e954f8 (HEAD -> main, origin/main, origin/HEAD) alisha's first file
cf2e9eb Initial commit

 

How git pull works?

Now next let's see how git pull would have handled this scenario. Alisha has again done some commit as you can see:

alisha@ubuntu:~/git_pull$ git log --oneline
3c81f88 (HEAD -> main, origin/main, origin/HEAD) First commit
8e954f8 aliasha's first file
cf2e9eb Initial commit

But the same is not available on deepak's local repo as he has not pulled the latest changes. So let's perform a git pull:

deepak@ubuntu:~/git_pull$ git pull origin main

Now if you compare the difference in the output compared to git fetch in the previous section, we have some new entry which I have highlighted in the sample output below.

git fetch vs git pull Explained [With Examples]

With git pull, both git fetch + git merge has been performed. This should explain the basic difference between both the commands.

You can also verify the commit history:

deepak@ubuntu:~/git_pull$ git log --oneline
3c81f88 (HEAD -> main, origin/main, origin/HEAD) First commit
8e954f8 aliasha's first file
cf2e9eb Initial commit

 

Conclusion

With this exercise now we learned that git fetch will only fetch the refs and tags from the remote repository but it will not merge them into your current branch. You must explicitly use git rebase to rebase your local repo with the remote repository and merge the changes.

While git pull performs fetch and subsequently merge operation so the end user does not need to perform a rebase operation separately

 

Example-3: Using git fetch + git merge vs git pull (on different branch)

In this section we will use git fetch + git merge and compare it with git pull operation. Technically in all the discussion we have mentioned that git pull = git fetch + git merge, but in the previous section we used git rebase instead of merge.

So, let's also take one example with git fetch + git merge operation. In the following example, both the users are working on main branch.

 

How git fetch works

User alisha has done some new commits into the main branch and has pushed the same to remote repository. She is currently working on dev branch:

alisha@ubuntu:~/git_pull$ git branch
* dev
  main
  prod

Here she performs some commits and sends to remote repository:

alisha@ubuntu:~/git_pull$ echo "new text" >> new_file

alisha@ubuntu:~/git_pull$ git commit -m "added new text" -a

alisha@ubuntu:~/git_pull$ git push origin dev

Verify the commit history:

alisha@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

Next user deepak wants to fetch and merge the changes from dev branch into prod branch. So he switches to prod branch and lists the available commits from the prod branch:

deepak@ubuntu:~/git_pull$ git checkout prod
Branch 'prod' set up to track remote branch 'prod' from 'origin'.
Switched to a new branch 'prod'

deepak@ubuntu:~/git_pull$ git branch
  dev
  main
* prod

deepak@ubuntu:~/git_pull$ git log --oneline
83eccc0 (HEAD -> prod, origin/prod) Added prod_file
e27f9a2 (origin/dev, dev) Added new_file
5094f93 (origin/main, origin/HEAD, main) Second commit
3c81f88 First commit
8e954f8 aliasha's first file
cf2e9eb Initial commit

Next deepak performs a fetch operation which will fetch all the changes from dev branch into the prod branch:

deepak@ubuntu:~/git_pull$ git fetch origin dev
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 246 bytes | 246.00 KiB/s, done.
From gitlab.com:golinuxcloud/git_pull
 * branch            dev        -> FETCH_HEAD
   e27f9a2..126cd7c  dev        -> origin/dev

But our commit history has not changed. that's because the changes are not merged yet, so we have a window to take care of any conflicts which can be common when merging two branches.

Here you can check the list of changes between local repo on prod branch vs dev branch on remote repo.

deepak@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

Next you can continue with the merge operation to merge dev branch into prod branch:

deepak@ubuntu:~/git_pull$ git merge origin/dev
Merge made by the 'recursive' strategy.
 new_file | 1 +
 1 file changed, 1 insertion(+)

Verify the available commits. Now we have a new commit ID which was used to merge the changes between dev and prod branch.

deepak@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

 

How git pull works

We perform the same exercise with git pull this time. Alisha has again done some changes as part of e2fe8c0 ID and pushed to dev branch of the remote repository:

alisha@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

Next deepak will perform git pull to directly merge the changes from dev branch into prod branch.

deepak@ubuntu:~/git_pull$ git branch

Sample Output:
git fetch vs git pull Explained [With Examples]

deepak@ubuntu:~/git_pull$ git pull origin dev

Sample Output:
git fetch vs git pull Explained [With Examples]

As you can see, the pull action has done fetch + merge operation combined. You can also verify the same by checking the commit history:

deepak@ubuntu:~/git_pull$ git log --oneline

Sample Output:
git fetch vs git pull Explained [With Examples]

 

Conclusion

Here we learned that if we are using git fetch to fetch the changes from a different branch then git merge can be used to merge both the branch. Although with git merge you will have one additional commit ID.

git fetch vs git pull Explained [With Examples]

 

But the same thing happens with git pull, the only difference is that as expected git pull will not give you an opportunity to check for any merge conflicts. But again in such cases the pull operation will fail and will work only once you have fixed any conflicts

git fetch vs git pull Explained [With Examples]

 

What's Next

git pull vs git pull --rebase explained with examples

 

Summary

From the example above you will notice that by using git fetch compared to git pull we first fetched the remote changes, checkout and then merge. On the other hand, updating the changes using git pull is an express procedure combining fetch and merge.

 

Further reading

Git-fetch vs git-pull

 

Views: 5

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can reach out to him on his LinkedIn profile or join on Facebook page.

Categories GIT

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment