Git PULL vs FETCH

As we wade and plow through the files working, there are points in time when we need to review what-all changes we made. Sometimes even why we made those in first place. Wherein comes the version control systems .

Git as it’s definition says on official source,

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.

And it has a lot many small caveats and features which become almost a muscle memory as you work with git over the time. Since we devs favor CLI over GUI, there are always some command which are HOTTT !! in market forever and so are asked as a rite of passage in interviews.
One such eternal question among many others is difference between git pull and git fetch . For someone very keen on thinking IT is all about “meaningful” words, set to meaningful tasks, this is huge disappointment ask google meaning of fetch and pull , it says they are almost the same.
But for git NOPE! they are different. Like water and fire.


In git a fetch essentially is a query to update information from the remote source. It’s like going to online shopping site and checking-in for your favorite product and adding it to cart if you find desirable update, you don’t buy it though! It’s just there FYI.
A pull is like going to shopping site and then casually wandering in electronics section for products, and bam!! suddenly you own a 52 inch ultra-modern-not-needed TV. Hey it wasn’t intentional but a pull is like that, it updates everything local to match remote changes.

git pull = git fetch + git merge

Now let’s see the game in action.

Clone a repository , You should see a unimaginatively named example directory in your current working directory, get inside the directory. When you clone a repository or repo ,as we call it, essentially makes a copy of everything that remote repository has.

# shows all branches
git branch -a 

  main
* trial-branch
  trial-five
  trial-four
  trial-one
  trial-three
  trial-two
  remotes/origin/HEAD -> origin/main
  remotes/origin/main
  remotes/origin/trial-branch
  remotes/origin/trial-five
  remotes/origin/trial-four
  remotes/origin/trial-one
  remotes/origin/trial-three
  remotes/origin/trial-two

# shows many branches, branches with *remote* suffix are remote branches and others are local 

This shows that currently I am on local-branch called trial-branch. If you list the content, a README.md is found here with just one word inside FirstName

Now let’s go to github and make a change in this file. Any change.
I added another word LastName and commit the change, so now the file looks something like this,

FirstName LastName

Now keep in mind that we made this change at the remote and not at our local clone/copy of file.

Perform a git fetch on your cli.

 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), 675 bytes | 1024 bytes/s, done.
From github.com:mohitwasnik132/example
   8a8f3cf..c3ab2d9  trial-branch -> origin/trial-branch

ignore the jargon for a moment and focus on last line.
what do you see?

8a8f3cf..c3ab2d9  trial-branch -> origin/trial-branch

this means.. there is some change in origin/trial-branch commit id 8a8f3cf..c3ab2d9 which is not reflected in local branch we are on, the trail-branch
can be easily checked,

mohit@DESKTOP-HOME: example| on  trial-branch

cat README.md

FirstName

So, the change we made at remote hasn’t been reflected but git informed us that there is a change in the branch, even if it isn’t showing what change, it has given a commit id which can be checked for particular change.

Let’s switch to remote branch and check what this supposed change is.( since we only have one file, it’s obvious that we check README.md again)

mohit@DESKTOP-HOME: example| on trial-branch

git checkout origin/trial-branch
.
.
.

mohit@DESKTOP-HOME: example| on  c3ab2d9

cat README.md

FirstName LastName

So the change can be seen.

What does this prove?
This proves that in simple terms, A git fetch will READ the changes from the remote repository but it does NOT WRITE them in the local repository.

To write these changes we have to perform a separate merge operation.

mohit@DESKTOP-HOME: example| on  c3ab2d9

git checkout trial-branch

mohit@DESKTOP-HOME: example| on  trial-branch

git merge origin/trial-branch

Updating 8a8f3cf..c3ab2d9
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)

Now again if we check README.md it’s reflecting the change we made earlier in remote branch, the local had no idea about.

mohit@DESKTOP-HOME: example| on  trial-branch

cat README.md

FirstName LastName
what’s the use of git pull then?

Git pull is best when you know and trust the changes in remote repository will not hurt your current work.

A git pull always creates a new local merge commit which has all the all the remote commits or to word it better, changes missing in the local branch compared to remote. Git pull is usually done with caution and with suitable strategies such as  a rebase merging strategy that is using git pull with --rebase option.

It doesn’t ask if you need those changes, it just pulls and merges them right into work which wrecks havoc if not done carefully. So, as a beginner it’s good to be patient and do a fetch instead of a pull

always remember,

PULL = FETCH + MERGE and no asking. No consulting. It’s just a leap of faith.

This was a long blog but I hope someone benefits from the details I tried to put in.
See you in next blog!