Alexander Mills
Alexander Mills

Reputation: 100010

How is `git pull --rebase` different than `git reset --soft origin/b`

I am trying to understand git pull --rebase...in order to do so, how is that command different from:

git fetch origin
git reset --soft remotes/origin/foo
git add .
git commit -am "bar"
git merge remotes/origin/foo

is git pull --rebase the same as the above commands or different? Certainly is less verbose, obviously.

Upvotes: 0

Views: 479

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 50864

No, they are quite different.

Assuming you have master checked out with a clean tree, your proposed set of commands will have the effect of pointing master at a single commit whose parent is the fetched upstream but whose content has the effect of replacing the new upstream tree with a copy of your pre-fetch master, without merging any of the upstream changes. (In particular, the final git merge remotes/origin/foo will always say "Already up-to-date." and never make any changes.)

That's because the command:

git reset --soft remotes/origin/foo

sets master to point to remotes/origin/foo without changing the current working directory (or index). Then, the command:

git commit -am "bar"

checks in a single commit for the (unchanged) tree from your current master. As far as Git is concerned, you just freshly fetched the upstream, and then methodically changed it to look exactly like your own master based on an earlier upstream, undoing any changes made since your previous pull, and then checked it in on top of the upstream. Since this commit is now a descendent of upstream, it's already considered merged, and the:

git merge remotes/origin/foo

will have no effect.

In constrast, git pull --rebase is the equivalent of

git fetch origin
git rebase remotes/origin/foo  # or wherever you pull from

This has the effect of replaying the sequence of commits that have been made on master since you last pulled from upstream on top of the upstream branch and pointing master at the result.

So, it differs from the above commands in that it adds a sequence of commits to upstream instead of adding a single commit, and it replays the contents of the commits (which means it tries to replay the changes made in those commits) on top of upstream, instead of replacing upstream with the old contents of master and obliterating upstream changes. In the end, master is still a descendent of remotes/origin/foo, so running:

git merge remotes/origin/foo

would still do nothing, but it doesn't have to do anything, because newly fetched upstream changes will have been incorporated into the new master branch.

Upvotes: 1

Related Questions