git pull vs git pull --rebase explained with examples

git pull vs git pull --rebase - Brief Overview

The git pull and git rebase are almost similar with some differences. You may have already heard of git fetch command which will fetch down all the changes from the remote repository server to your local workstation that you don’t have yet, it will not modify your working directory at all. It will simply get the data for you and let you merge it yourself. Next you can use git merge to merge the changes. Now instead of performing this git fetch followed by git merge, you can directly use git pull.

The git rebase is sort of an alternative to merge functionality. Instead of creating a new commit that combines the two branches, the git rebase moves the commits of one of the branches on top of the other.

Advertisement

 

Let us explore each one of them individually.

 

git pull command (without rebase)

In truth, git pull is a super command; in fact, it is basically the sum of two other git commands, git fetch and git merge. The git pull command is used to pull the remote modifications to the local repository.

To understand this let us explore both commands individually:

 

Use git fetch + git merge separately

  • The git fetch command communicates with a remote repository and fetches down all the information that is in that repository that is not in your current one and stores it in your local database.
  • When you clone a repository, local versions of its branches are also maintained. The fetch command updates these local versions with the latest commits from the remote.
  • It could happen that someone pushed a commit or more on top of a branch, but you realized those commits are not good for you, or simply they are just wrong. So, using git fetch, you can get and inspect them before applying them on your local branch with a git merge.
  • Here I have cloned a project into my local workstation from gitlab. I am using new-feature branch of this project. Now there is another user alisha who is also using the same branch of the same project.

Now as deepak user I have made some commits and pushed the same to remote branch:

deepak@ubuntu:~/gc_dev$ git commit -m "commit-3" -a
[feature dcdbcb1] commit-3
 1 file changed, 1 insertion(+), 1 deletion(-)

deepak@ubuntu:~/gc_dev$ git push origin feature
...
To gitlab.com:golinuxcloud/gc_dev.git
   a12c5d0..dcdbcb1  feature -> feature

Check the list of commit ids, here dcdbcb1 is my latest commit ID

deepak@ubuntu:~/gc_dev$ git log --oneline
dcdbcb1 (HEAD -> feature, origin/feature) commit-3
a12c5d0 commit-2
80be119 commit-1
a8afb3c (origin/main, main) commit-C
e3ab8c3 commit-B
54a79f1 commit-A

Now use alisha tries to fetch the latest refs and commits from remote branch and stores it locally:

Advertisement
alisha@ubuntu:~/gc_dev$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), 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), 251 bytes | 125.00 KiB/s, done.
From gitlab.com:golinuxcloud/gc_dev
   a12c5d0..dcdbcb1  feature    -> origin/feature

As you see the commit information from dcdbcb1 ID is fetched but the actual commit is not merged which is why our latest commit still shows commit-2:

alisha@ubuntu:~/gc_dev$ git log --oneline
a12c5d0 (HEAD -> feature) commit-2
80be119 commit-1
a8afb3c (origin/main, origin/HEAD, main) commit-C
e3ab8c3 commit-B
54a79f1 commit-A

As you can see the latest changes were fetched but were not merged in your local workstation. Now at this stage you can manually perform a git merge to merge the changes:

alisha@ubuntu:~/gc_dev$ git merge
Updating a12c5d0..dcdbcb1
Fast-forward
 file2 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Now alisha can see that the latest commit from user deepak is also applied to your local workstation:

alisha@ubuntu:~/gc_dev$ git log --oneline
dcdbcb1 (HEAD -> feature, origin/feature) commit-3
a12c5d0 commit-2
80be119 commit-1
a8afb3c (origin/main, origin/HEAD, main) commit-C
e3ab8c3 commit-B
54a79f1 commit-A

 

Use git pull  (git fetch + git merge)

Now we will just use git pull instead of using the fetch and merge command separately. So I have made one more commit with ID db1a9f2 using deepak user as you can check below from deepak's workstation:

 deepak@ubuntu:~/gc_dev$ git log --oneline
db1a9f2 (HEAD -> feature, origin/feature) commit-4
dcdbcb1 commit-3
a12c5d0 commit-2
80be119 commit-1

Now let's directly perform a git pull from alisha's workstation:. But first make sure alisha is connected to the feature branch:

alisha@ubuntu:~/gc_dev$ git branch
* feature
  main

Next we will initiate the git pull from feature branch on remote repository:

alisha@ubuntu:~/gc_dev$ git pull origin feature
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), 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), 251 bytes | 62.00 KiB/s, done.
From gitlab.com:golinuxcloud/gc_dev
 * branch            feature    -> FETCH_HEAD
   dcdbcb1..db1a9f2  feature    -> origin/feature
Updating dcdbcb1..db1a9f2
Fast-forward
 file2 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

As you can see above, the pull command has fetched the refs and commits and has also merged the recent changes from deepak to alisha's local repository:

alisha@ubuntu:~/gc_dev$ git log --oneline
db1a9f2 (HEAD -> feature, origin/feature) commit-4
dcdbcb1 commit-3
a12c5d0 commit-2
80be119 commit-1
a8afb3c (origin/main, origin/HEAD, main) commit-C
e3ab8c3 commit-B
54a79f1 commit-A

 

How git merge works

  • I have already covered git merge in detail with multiple examples
  • Suppose you have a main branch which contains the code changes for your application.
  • Now there are multiple bugs reported on this main branch, so each bug is assigned to a different developer. Now we assign a different branch to each developer so they can continue with the bug fix changes while the main branch continues to have stable code.
  • Once the developer has fixed and tested the changes then they will switch to the main branch and then merge their branch with main branch. This would merge all the commits which were done in the developer branch
git pull vs git pull --rebase explained with examples
git merge

In this example diagram as you can see, the developer has created a new branch by using git checkout -b feature. in the feature branch he does 2 commits and then now since he knows the bug has been fixed so he switches to main branch and merge his changes.

Advertisement

The basic git workflow of git merge would be:

## Create and switch to a bugfix branch
## If a branch already exists then -b can be removed from this command
## -b will create a new branch on your local workstation
git checkout -b bugfix

## work on your changes
git add 
git commit 

## you may also push the changes to remote branch to save the work
## this will create a branch bugfix on remote repository
git push origin bugfix

##To merge, switch to the branch into which you plan to merge your changes
git checkout main

## Perform the merge
git merge bugfix

 

How git pull works

We have already covered this part in detail with examples in the above section so I will just brief out the workflow:

## user1 pulls feature branch
user1$ git pull feature
user1$ git checkout feature

## user2 pulls feature branch
user2$ git pull feature
user2$ git checkout feature

## user1 makes some changes and pushes to remote feature branch
user1$ git commit -m "some message" -a
user1$ git push origin feature

## user2 pulls the latest changes
## This command will fetch + merge the changes from user1 into user2 local workstation
user2$ git pull origin

 

git pull --rebase command

  • Now you must be wondering when git pull is already getting all the files, commits, refs from the remote repository then why should I use rebase with git pull ?
  • The main reason we do a git pull --rebase over git pull is because it avoids loops in the project history.
  • For instance, the master branch has had many changes since you began working on your feature branch. You want to acquire the newest updates from the master branch to your local branch while maintaining a clean history of your branch to appear as you have been working off the latest master branch.
  • Git rebase guarantees a clean merge between your feature branch back into the master branch without keeping commit history.
  • Why then do we need a clean history? The importance of a clean history becomes evident when carrying out Git operations to explore the foundation of a regression. 
  • Quite literally, the process of rebasing is a way of rewriting the history of a branch by moving it to a new “base” commit.

 

git pull vs git pull --rebase explained with examples
git pull

If you perform a git pull of a branch with some merge commits, then the commit history would be like this:

git pull vs git pull --rebase explained with examples
git pull --rebase

But when we perform a git pull --rebase then the commit history would be like this:

 

How git rebase works

Let me explain this part with an example. I have made some commits in the main branch as you can see here:

deepak@ubuntu:~/gc_dev$ git log --oneline
0320b58 (HEAD -> main, origin/main) commit-E
6d2bc8b commit-D
a8afb3c commit-C
e3ab8c3 commit-B
54a79f1 commit-A

Now some other developer was also working on the feature branch and they also did some commits on the feature branch:

deepak@ubuntu:~/gc_dev$ git log --oneline
fdff32d (HEAD -> feature, origin/feature) commit-5
db1a9f2 commit-4
dcdbcb1 commit-3
a12c5d0 commit-2
80be119 commit-1
a8afb3c commit-C
e3ab8c3 commit-B
54a79f1 commit-A

The feature branch also contains reference of main branch as we had checked out feature branch after commit-C. Now let us merge feature branch into main branch.

First we should switch to main branch:

deepak@ubuntu:~/gc_dev$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

Next merge the feature branch into main branch:

deepak@ubuntu:~/gc_dev$ git merge feature
Merge made by the 'recursive' strategy.
 file2 | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 file2

Check the commit history, a new commit b9a3bcb has been created for the merge:

deepak@ubuntu:~/gc_dev$ git log --oneline
b9a3bcb (HEAD -> main) Merge branch 'feature'
fdff32d (origin/feature, feature) commit-5
0320b58 (origin/main) commit-E
6d2bc8b commit-D
db1a9f2 commit-4
dcdbcb1 commit-3
a12c5d0 commit-2
80be119 commit-1
a8afb3c commit-C
e3ab8c3 commit-B
54a79f1 commit-A

As you can see now the commit history contains the changes from both main and feature branch but it is not in properly aligned.

So we use rebase the main branch:

deepak@ubuntu:~/gc_dev$ git pull --rebase
Successfully rebased and updated refs/heads/main.

Now verify the commit history, as you can see the commits are now aligned properly in a single line as we had shown in the image and the extra commit which was created for the merge request is also not there any more:

deepak@ubuntu:~/gc_dev$ git log --oneline
24084d3 (HEAD -> main) commit-5
8748146 commit-4
08ffd72 commit-3
cb4fcac commit-2
cba988c commit-1
0320b58 (origin/main) commit-E
6d2bc8b commit-D
a8afb3c commit-C
e3ab8c3 commit-B
54a79f1 commit-A

So I hope this should help you clear your doubts of difference between git pull and git pull with rebase.

When to use git pull --rebase

  1. When multiple individuals are working on the same branch
  2. When you want to crush multiple commits
  3. When you want to overwrite the history. 
  4. When you want to repeat each commit and add the changes.

 

Pros

  1. Git rebase can streamline complex history 
  2. Controlling a single change is easy
  3. It avoids merging commits in busy repositories 

 

Cons

  1. Crushing features to a handful of changes can hide the data.
  2. Rebasing on public repositories is not advisable. Rewriting history on public/shared branches can make teamwork suffer from breakage.
  3. It has more work since one requires to keep updating the feature branches every time. 
  4. Rebasing with a remote repository requires one to force push. This has been seen as a bigger problem to people who have not set git push as default.   

 

Summary

This  two git commands are not interchangeable.

Git pull downloads the newest changes from the remote repository and applies the changes to your local repository. Generally, git pull is git fetch and git merge. 

Rebasing on the other hand can be a replacement for git merge.  Instead of making a new commit that joins the two branches and leaves  a commit history, it adds your changes above other new remote changes at the same time rewrite the commit history,  making the commit history much cleaner that git merge.

You can also pull using rebase instead of git merge, by the use of git pull --rebase. The changes made on your local repository will be added on top of the changes from remote repository and your local repository will be up to date.

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

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 either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment