360

I started using git sometime back and do not fully understand the intricacies. My basic question here is to find out the difference between a git pull and git pull --rebase , since adding the --rebase option does not seem to do something very different : just does a pull.

Please help me with understanding the difference.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Rndm
  • 6,710
  • 7
  • 39
  • 58
  • 7
    Related: [When should I use git pull --rebase?](http://stackoverflow.com/q/2472254/456814). –  May 16 '14 at 20:26
  • 3
    Possible duplicate of [git pull VS git fetch git rebase](http://stackoverflow.com/questions/3357122/git-pull-vs-git-fetch-git-rebase) – T J Apr 27 '16 at 07:54
  • Usefull link: https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase – Taras Melnyk Mar 09 '18 at 08:46

5 Answers5

371

git pull = git fetch + git merge against tracking upstream branch

git pull --rebase = git fetch + git rebase against tracking upstream branch

If you want to know how git merge and git rebase differ, read this.

Community
  • 1
  • 1
mvp
  • 111,019
  • 13
  • 122
  • 148
  • 16
    It's worth noting that saying `git pull --rebase` is the same as `git fetch` and `git rebase` is basically how it is, but it's not *exactly* semantically equivalent. There are some differences, some of which are explained here. http://gitolite.com/git-pull--rebase – w0rp Aug 20 '15 at 09:47
  • 8
    It's what I would call a "convenient lie," to borrow a phrase from Scott Meyers. It's a good way to explain it regardless. – w0rp Aug 20 '15 at 09:49
  • Very briefly. I can't understand the difference. What so important about `fetch`? – Green Nov 06 '19 at 08:36
259

Sometimes we have an upstream that rebased/rewound a branch we're depending on. This can be a big problem -- causing messy conflicts for us if we're downstream.

The magic is git pull --rebase

A normal git pull is, loosely speaking, something like this (we'll use a remote called origin and a branch called foo in all these examples):

# assume current checked out branch is "foo"
git fetch origin
git merge origin/foo

At first glance, you might think that a git pull --rebase does just this:

git fetch origin
git rebase origin/foo

But that will not help if the upstream rebase involved any "squashing" (meaning that the patch-ids of the commits changed, not just their order).

Which means git pull --rebase has to do a little bit more than that. Here's an explanation of what it does and how.

Let's say your starting point is this:

a---b---c---d---e  (origin/foo) (also your local "foo")

Time passes, and you have made some commits on top of your own "foo":

a---b---c---d---e---p---q---r (foo)

Meanwhile, in a fit of anti-social rage, the upstream maintainer has not only rebased his "foo", he even used a squash or two. His commit chain now looks like this:

a---b+c---d+e---f  (origin/foo)

A git pull at this point would result in chaos. Even a git fetch; git rebase origin/foo would not cut it, because commits "b" and "c" on one side, and commit "b+c" on the other, would conflict. (And similarly with d, e, and d+e).

What git pull --rebase does, in this case, is:

git fetch origin
git rebase --onto origin/foo e foo

This gives you:

 a---b+c---d+e---f---p'---q'---r' (foo)

You may still get conflicts, but they will be genuine conflicts (between p/q/r and a/b+c/d+e/f), and not conflicts caused by b/c conflicting with b+c, etc.

Answer taken from (and slightly modified):
http://gitolite.com/git-pull--rebase

Community
  • 1
  • 1
Mauri Lopez
  • 2,864
  • 1
  • 17
  • 19
  • 12
    This is the best answer. You might want to change the final result to `a---b+c---d+e---f---p'---q'---r' (foo)` since rebase changes hashes. – Bastien Jan 21 '14 at 09:59
  • 28
    This answer was copied and pasted verbatim from http://gitolite.com/git-pull--rebase and should include attribution per the license on that page. – Wildcard Dec 02 '15 at 23:40
  • This is a great explanation. But I had a situation, where I had commit `A`, and I sent a PR to the upstream repo which got accepted. Then when I did `git pull --rebase` against the upstream repo, I didn't get a new `A'` commit on top of the pulled upstream repo. In fact no `A'` existed at all. Is this because `A` was merged into the system? Or is it because there was no difference between the upstream and my rebased onto version? – CMCDragonkai Feb 24 '16 at 07:41
  • I'm currently going through the Git tutorial and was using this response to further understand a `git pull --rebase`. But one thing that confuses me in this hypothetical situation is that the upstream maintainer has changed project history that has already been pulled into local developer's repositories. Isn't this just bad practice in general? If he wanted to squash commits/rewrite history, it should have been done before integrating it into the central repository to avoid these type of conflicts. – bmcentee148 May 08 '17 at 17:42
  • Not long after this answer was originally posted, `git rebase` was modified so that it now also performs the additional steps done by `git pull --rebase`. – Buster Jan 15 '21 at 16:38
50

Suppose you have two commits in local branch:

      D---E master
     /
A---B---C---F origin/master

After "git pull", will be:

      D--------E  
     /          \
A---B---C---F----G   master, origin/master

After "git pull --rebase", there will be no merge point G. Note that D and E become different commits:

A---B---C---F---D'---E'   master, origin/master
Deqing
  • 14,098
  • 15
  • 84
  • 131
10

In the very most simple case of no collisions

  • with rebase: rebases your local commits ontop of remote HEAD and does not create a merge/merge commit
  • without/normal: merges and creates a merge commit

See also:

man git-pull

More precisely, git pull runs git fetch with the given parameters and calls git merge to merge the retrieved branch heads into the current branch. With --rebase, it runs git rebase instead of git merge.

See also:
When should I use git pull --rebase?
http://git-scm.com/book/en/Git-Branching-Rebasing

Community
  • 1
  • 1
drahnr
  • 6,782
  • 5
  • 48
  • 75
  • 3
    And in case of collisions ? – Rndm Sep 21 '13 at 08:34
  • 1
    You will get asked to resolve them manually and then - continue with rebase:`git sdd modified-file; git rebase --continue` or merge:`git add modified-file; git commit;` where `modified-file` is your local file you modified manually/mergetool – drahnr Sep 21 '13 at 08:37
  • What so special about `fetch`? Why did they created two `rebase` flows? 1) `git rebase` and 2) `git pull --rebase`? – Green Nov 06 '19 at 09:47
9

For this is important to understand the difference between Merge and Rebase.

Rebases are how changes should pass from the top of hierarchy downwards and merges are how they flow back upwards.

For details refer - http://www.derekgourlay.com/archives/428

Sagar Mody
  • 525
  • 5
  • 9
  • I think that your answer offers a much simpler explanation that is not obvious on the rest of the answers above. Thanks. – Aaron C May 24 '16 at 20:58