306

Another question says that git pull is like a git fetch + git merge.

But what is the difference between git pull and git fetch + git rebase?

Josh Correia
  • 2,133
  • 1
  • 17
  • 29
michael
  • 93,094
  • 111
  • 230
  • 334

2 Answers2

349

It should be pretty obvious from your question that you're actually just asking about the difference between git merge and git rebase.

So let's suppose you're in the common case - you've done some work on your master branch, and you pull from origin's, which also has done some work. After the fetch, things look like this:

- o - o - o - H - A - B - C (master)
               \
                P - Q - R (origin/master)

If you merge at this point (the default behavior of git pull), assuming there aren't any conflicts, you end up with this:

- o - o - o - H - A - B - C - X (master)
               \             /
                P - Q - R --- (origin/master)

If on the other hand you did the appropriate rebase, you'd end up with this:

- o - o - o - H - P - Q - R - A' - B' - C' (master)
                          |
                          (origin/master)

The content of your work tree should end up the same in both cases; you've just created a different history leading up to it. The rebase rewrites your history, making it look as if you had committed on top of origin's new master branch (R), instead of where you originally committed (H). You should never use the rebase approach if someone else has already pulled from your master branch.

Finally, note that you can actually set up git pull for a given branch to use rebase instead of merge by setting the config parameter branch.<name>.rebase to true. You can also do this for a single pull using git pull --rebase.

Sachin Joseph
  • 15,841
  • 3
  • 36
  • 54
Cascabel
  • 422,485
  • 65
  • 357
  • 307
  • 39
    What happens if you were to rebase after someone had already pulled from your master branch? Would that break the repo? – Didier A. Mar 22 '11 at 06:36
  • 12
    How do you know if someone has pulled from your master branch? – Frank Aug 07 '12 at 05:47
  • 32
    If you don't know for sure that someone *hasn't*, you should assume that they have. – Chris Down Feb 11 '13 at 06:20
  • 4
    I was just thinking that unless you're also pushing changes somewhere other than origin/master, I don't see ever running into the problem of someone else having pulled the changes in question, because if you had already pushed these changes to origin/master, there would be nothing to rebase in the first place. It seems to me that the warning really only matters in cases of where you've got something more complex than X -> origin/X, but I could be wrong. If someone knows of a scenario I'm overlooking, please share. – neverfox Jun 26 '13 at 17:00
  • @neverfox The basic scenario is: I push A to origin/master. Someone else pulls it. I rebase, changing A to A' (or something more complex) and force push that. Now when the other person pulls, they will be trying to merge A and A' (or with pull --rebase, rebase A on top of A'). Both are recipes for something on the scale from headaches to disaster, depending on the competence of the other person. – Cascabel Jun 26 '13 at 18:28
  • @neverfox Actually, pull --rebase tries to be smarter, but I'm not sure if it's universally successful. – Cascabel Jun 26 '13 at 18:34
  • This might sound picky but it's just to aid my understanding: On your diagram if the lines from left to right correspond to relative time, wouldn't the end result be `- o - o - o - o - P - A - Q - B - R - C`, (i.e. the time order of the commits is preserved)? – Steve Chambers Nov 06 '13 at 08:59
  • 1
    @SteveChambers No, that's not the result. The lines simply represent commit ancestry, i.e. A is the parent of B. There's not any implication about whether Q or B was first in time. All these operations are based on commit graphs, not time. Rebase simply transplants some commits, with the result as I showed no matter what the commit timestamps are. – Cascabel Nov 06 '13 at 14:57
  • 1
    @SteveChambers The rebase in question here is master onto origin/master. Git looks at master, starts at commit C, works back until a common ancestor with origin/master, finds the common parent of A and P, so it knows it needs to move everything from A on, so it moves `A - B - C` onto origin/master (commit R) and does so, ending up with `P - Q - R - A - B - C`. – Cascabel Nov 06 '13 at 15:04
  • 1
    If you want the default behavior to be rebase instead of merge for each branch you check out, you can configure this globally by doing `git config --global branch.autosetuprebase always` – mmjmanders May 16 '14 at 14:35
  • You should better test your work if you use Rebase. If your changes are incompatible with commits done since version (H), with Rebase no-one will know why you committed broken code because it will look like you made the changes on the latest version (C). Merge reflects reality better, i.e. it will capture the fact that you worked on the (H) version and not (C). – rustyx Jul 19 '14 at 20:07
  • @didibus: from http://rypress.com/tutorials/git/centralized-workflows.html: Consider what would have happened had Mary rebased after pushing to the central repository. She would be re-writing commits that other developers may have already pulled into their project. – Maria Ines Parnisari Sep 14 '14 at 19:52
  • is there any chance of code missing or missing file in git pull? – urjit on rails Oct 01 '14 at 10:54
  • "You should never use the rebase approach if someone else has already pulled from your master branch." I find this sentence very confusing because I would expect that master should normally be a local branch which should not be pulled by someone? Is there any plausible scenario where a branch is not on a remote (remote/master) and could be pulled by someone? – 6bf6411707 Jan 26 '19 at 15:14
17

TLDR:

git pull is like running git fetch then git merge
git pull --rebase is like git fetch then git rebase

In reply to your first statement,

git pull is like a git fetch + git merge.

"In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD" More precisely, git pull runs git fetch with the given parameters and then calls git merge to merge the retrieved branch heads into the current branch"

(Ref: https://git-scm.com/docs/git-pull)


For your second statement/question:

'But what is the difference between git pull VS git fetch + git rebase'

Again, from same source:
git pull --rebase

"With --rebase, it runs git rebase instead of git merge."


Now, if you wanted to ask

'the difference between merge and rebase'

that is answered here too:
https://git-scm.com/book/en/v2/Git-Branching-Rebasing
(the difference between altering the way version history is recorded)

gawkface
  • 1,173
  • 16
  • 21
  • 3
    I'd like to mention that "git pull --rebase" is like "git fetch then git rebase" most of the time - but not always. In some situations, "git pull --rebase" does a bit more. See this often referenced example here: https://gitolite.com/git-pull--rebase – Daniel K. Jul 22 '19 at 14:20
  • 1
    Thank you so much for your answer. I really understand the way `git fetch + git rebase` commands work from now. There's no more or less conflict on our git tree from now :) – Travis Le Nov 07 '19 at 07:17
  • 1
    @DanielK, `git rebase` also does those additional steps, since shortly after that blog post was written. See the discussion of `--fork-point` in `git help rebase`. – Buster Jan 15 '21 at 16:36