Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when I 'git pull --rebase origin development' from within a feature branch?

Let's say I have a feature branch called FeatureA, and it is out of sync with (remote) development on which it is based. Normally I would rebase my branch by calling git rebase development (after syncing my local development with origin/development naturally).

Today, I do it different and call git pull --rebase origin development from my feature-branch instead. Now, what is the difference?

like image 446
M Jacobs Avatar asked Mar 11 '14 20:03

M Jacobs


2 Answers

git pull --rebase origin development is a shortcut to these commands:

git fetch origin development
git rebase origin/development

That is, fetch origin/development and then rebase the current branch on top of it.

UPDATE

As @torek pointed out:

Yes, except that the two-argument version of fetch does not update origin/development in git 1.8.3 or earlier. (The rebase result is the same, but origin/development does not move.)

like image 56
janos Avatar answered Oct 21 '22 03:10

janos


Short version: if the rebase goes well, it works fine. If not, it still works as well as it should, it just might be a bit confusing in a graphical viewer.


As always, git pull is basically git fetch followed by ... well, in this case, git rebase rather than git merge. So:

  • fetch from origin
  • fetch only the development branch and put that in FETCH_HEAD
  • then, instead of git merge <commit-ID-from-FETCH_HEAD>, use git rebase with that ID

So let's say the commit graph in your local tree looks like this (we'll assume you ran a git fetch at some point that updated origin/development with their commits E and F):

        C - D   <-- FeatureA
      /
A - B           <-- development
      \
        E - F   <-- origin/development

And, let's further assume that on origin, there's one more commit now on their branch named development. The fetch-from-origin step will pick it up and make FETCH_HEAD point to that, so let's draw it in as node G:

        C - D       <-- FeatureA
      /
A - B               <-- development
      \
        E - F       <-- origin/development
              \
                G   <-- FETCH_HEAD

(If your git is new enough, 1.8.4 or later, origin/development will also be updated at this time, to point at node G. If not, your local copy of their development, stored in your origin/development, lags behind. It won't really matter for the rebase, it will just change how you'll see the results in a git log --graph view or a graphical commit-tree viewer.)

Now the rebase will copy your FeatureA commits in the usual method for a rebase, and make FeatureA point to the copies, abandoning the original commits. We'll call the rebased ones C' and D':

        C - D       [abandoned]
      /
A - B               <-- development
      \
        E - F       <-- origin/development
              \
                G   <-- FETCH_HEAD
                  \
                    C' - D'   <-- FeatureA

If you run a plain git fetch at this point, or if you have the newer-enough git so that origin/development has moved; and if we drop the "abandoned" parts and simplify the drawing, it becomes:

A - B               <-- development
      \
        E - F - G   <-- origin/development
                  \
                    C' - D'   <-- FeatureA

If you fast-forward-merge your local branch-label development to match origin/development, it's even simpler to draw (drop the kink down from B to E and put both development and origin/development to the right of the arrow pointing to G).

like image 25
torek Avatar answered Oct 21 '22 01:10

torek