Is git pull the same as fetch and merge?

git pull is equivalent to git fetch followed by git merge on a branch from a remote repository. You cannot do git merge without doing git fetch. But when you use git pull, it will first fetch the latest information on commits in the remote repository and then issue a merge of the commits.

Let us check this through a hands-on example.

Consider the initial setup as shown. Using git branch, we can see that the branch name is main. And the branch has five commits.


~/repoone$ git branch
* main


~/repoone$ git log --oneline
4632c0d (HEAD -> main, origin/main, origin/HEAD, origin/maincopy) Adding empty directory
908d6ac Third commit in main
42296d0 Second commit in main
453424e This is first commit
2673111 Initial commit

If we check the remote repository in GitHub online, one more extra commit is available. Its id is 3f54558.

New commit  in online repository

If we use git status, it is unaware of this new commit. It says that the local branch is up to date with origin/main. But it is not.

~/repoone$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

When we issue git pull, it gets the latest updated information on the remote commits and merges them into the local branch. It first did git fetch to get updated info on the commits. Then, it issued git merge origin/master to merge the commits.

~/repoone$ 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), 667 bytes | 667.00 KiB/s, done.
From github.com:codeversionmaster/repoone
   4632c0d..3f54558  main       -> origin/main
Updating 4632c0d..3f54558
Fast-forward
 newfile | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 newfile

You can use git log –oneline and see that the local branch main has all the commits and is in sync with the main branch in the remote repository.

~/repoone$ git log --oneline
3f54558 (HEAD -> main, origin/main, origin/HEAD) This is new file
4632c0d (origin/maincopy) Adding empty directory
908d6ac Third commit in main
42296d0 Second commit in main
453424e This is first commit
2673111 Initial commit

Now, we will do one more commit directly in the online GitHub repository repoone and see how the local branch behaves. We will then check the behavior of git merge without any fetch. Then, we would issue “git fetch” followed by “git merge” to see how it is equivalent to issuing a git pull.

Below is the status of commits in the online repository after one more commit.

One more commit in online repository

At this time, if we issue git merge origin/main, it would show that the local branch is already up to date. It means that the local branch does not know about the latest additional commits that happened online.

~/repoone$ git merge origin/main
Already up to date.

So, we use git fetch to get the latest information about commits updated to the local git.

~/repoone$ git fetch origin
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 691 bytes | 691.00 KiB/s, done.
From github.com:codeversionmaster/repoone
   3f54558..bead66e  main       -> origin/main

Now, if you issue git merge origin/main, it will merge the latest commits also into the local branch.

~/repoone$ git merge origin/main
Updating 3f54558..bead66e
Fast-forward
 newfile | 1 +
 1 file changed, 1 insertion(+)

You can issue git log –oneline to see that the list of commits is updated and in sync with the remote repository.

~/repoone$ git log --oneline
bead66e (HEAD -> main, origin/main, origin/HEAD) Another change to new file
3f54558 This is new file
4632c0d (origin/maincopy) Adding empty directory
908d6ac Third commit in main
42296d0 Second commit in main
453424e This is first commit
2673111 Initial commit

This also proves that git pull when issued on a remote repository, is the combination of a fetch request followed by a merge request.