git pull *after* git rebase?
tl;dr You should update both
git pull and
git pull --rebase before rebasing
feature on top of
master. There is no need to do a
git pull after you have rebased your
feature branch on top of
With your current workflow, the reason why
git status is telling you this:
Your branch and 'origin/feature' have diverged, and have 27 and 2 different commits each, respectively.
is because your rebased
feature branch now has 25 new commits that aren't reachable from
origin/feature (since they came from the rebase on
master) plus 2 commits that are reachable from
origin/feature but have different commit IDs. Those commits contain the same changes (i.e. they're patch equivalent) but they have different SHA-1 hashes because they are based off of a different commit in
origin/feature than the one you rebased them on in your local repository.
Here's an example. Let's assume that this is your history before doing
git pull on
A - B - C (master) \ D - E (feature)
master got commit
A - B - C - F (master, origin/master) \ D - E (feature)
At that point, you rebase
feature on top of
master, which applies
A - B - C - F (master, origin/master) \ D - E (feature)
In the meantime, the remote branch
origin/feature is still based off commit
A - B - C - F (master, origin/master) \ \ \ D' - E' (feature) \ D - E (origin/feature)
If you do a
git status on
feature, Git will tell you that your
feature branch has diverged from
origin/feature with 3 (
E') and 2 (
E) commits, respectively.
E'contain the same changes as
Ebut have different commit IDs because they have been rebased on top of
The solution is to do
git pull on both
feature before rebasing
master. However, since you may have commits on
feature that you haven't yet pushed to
origin, you would want to do:
git checkout feature && git pull --rebase
to avoid creating a merge commit between
origin/feature and your local
Update on the consequences of rebasing:
In light of this comment, I expanded on the diverging branches. The reason why
git status reports that
origin/feature diverge after the rebase is due to the fact that rebasing brings in new commits to
feature, plus it rewrites the commits that were previously pushed to
Consider the situation after the pull but before the rebase:
A - B - C - F (master) \ D - E (feature, origin/feature)
At this point,
origin/feature point to the same commit
E—in other words, they're in "sync". After rebasing
feature on top of
master, history will look like this:
A - B - C - F (master) \ \ \ D' - E' (feature) \ D - E (origin/feature)
As you can see,
origin/feature have diverged, their common ancestor being commit
C. This is because
feature now contains the new commit
E' (read as "D prime" and "E prime") which are commits
E applied on top of
F. Even though they contain the same changes, Git considers them to be different because they have different commit IDs. Meanwhile,
origin/feature still references
At this point, you've rewritten history: you've modified existing commits by virtue of rebasing them, effectively creating "new" ones.
Now, if you were to run
git pull on
feature this is what would happen:
A - B - C - F (master) \ \ \ D' - E'- M (feature) \ / D - E - (origin/feature)
git pull does
git fetch +
git merge, this would result in the creation of the merge commit
M, whose parents are
If, instead, you ran
git pull --rebase (that is,
git fetch +
git rebase) then Git would:
C(the common ancestor of
However, noticing that
E' contain the same changes as
E, Git would just discard them, resulting in a history looking like this:
A - B - C - F (master) \ D - E - F' (feature) ^ (origin/feature)
Notice how commit
F, previously reachable from
feature, got applied on top of
origin/feature resulting in
F'. At this point,
git status would tell you this:
Your branch is ahead of 'origin/feature' by 1 commit.
That commit being, of course,
If the remote versions of
feature/branch are up-to-date individually, then simply reset your local feature branch
git checkout feature/branch git fetch origin feature/branch git reset --hard origin/feature/branch
then if you want to bring in changes in the
git rebase origin/master
When you rebased your feature branch on top of master, you created a bunch of new commits. However, your
origin/feature branch is still pointing to the old ones. This is the situation after the rebase:
C' (feature) B' A' * (master, origin/master) * * | C (origin/feature) | B | A |/ * some base commit
While the commit
A' contains a similar change set as commit
A, it is by no means the same commit. It contains a different tree, and has a different parent.
Now, when you try to pull
feature again, you try to create this history:
* (feature) |\ C'| B'| A'| * | (master, origin/master) * | * | | C (origin/feature) | B | A |/ * some base commit
You are merging two branches that have introduced very similar, jet different changes. This is bound to create a ton of conflicts, apart from being entirely pointless.
What you need to do is inform your upstream repo about the rebase by using
git push -f. This will loose the old history, and replace it with the rewritten one.
The alternative is to avoid using
git rebase on branches that you have already pushed to any other repository, or avoid
git rebase altogether. This is the cleaner approach: It results in the history as it has happened, instead of telling lies about history as
git rebase does. That's at least what I prefer.
have 27 and 2 different commits each is telling you that you now have 27 new commits from
master and 2 new commits in your branch that are not present in
origin/<yourbranch> has been massively changed by the rebase, it no longer has a common base with
origin/<yourbranch>. Therefore, you don't want to then pull the changes from
origin/<yourbranch> after the rebase, because, as you see, all H*** breaks loose.
If you know there are changes in
origin/<yourbranch> that you need in your local branch, then pull those before you rebase.
If you are sure no one has changed
origin/<yourbranch> since your last push (a safe bet if this is your own feature branch), you can use
push --force to put them into sync again. Then
origin/<yourbranch> will again have the same base as your local branch and that base will contain all the latest
ptpdlcUpdated on April 16, 2020
ptpdlc over 2 years
I have a feature branch, and a master branch.
Master branch has evolved and I mean to have those updates to diverging as little as possible from master branch.
git pullin both branches,
git checkout feature/branchand finally
git rebase master.
Now here I either expect everything to work smoothly or conflicts showing up that I need to resolve before continuing rebase until all master commits are re-applied successfully on feature branch.
Now what really happened in my case is something I do not understand:
$>git rebase master First, rewinding head to replay your work on top of it... Applying: myFirstCommitDoneOnTheBranch Applying: myOtherCommitDoneOnTheBranch $>git status On branch feature/branch Your branch and 'origin/feature/feature' have diverged, and have 27 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) nothing to commit, working tree clean $>git pull *load of conflicts*
Now, as much as I can understand he load of conflicts after the pull; I do not understand the need for a pull. Logically, it should rollback to master when it got branched, save the commits made on the branch, forward to latest commit on master and then apply the saved commits.
I do not understand to what the
Applyingmessage refers to: what is applying the commits on which version?
ptpdlc almost 6 yearsThank you for this. But what I do not get is that I did do a git pull --rebase on both branches before rebasing and I end up with this. Just to make things clear: I am not rebasing on top of master but on develop though it should not change anything (and yes the command I use is git rebase develop not git rebase master). Still how come I still end up with this "diverged branches" thing?
Michał Poreda almost 6 years@tisek I expanded on my previous answer. I hope this clarifies things.
ptpdlc almost 6 yearsThis is very interesting. I am just not completely sure of what should be done: should I push (actually, will git let me do this ?) after my rebase? since from your explanation, the state of the feature branch locally is that it now has all updates from master + the feature specific ones? or run a git pull --rebase in order for git to (not) reapply the changes (except for the pure-master-ones (the F that becomes F' on the branch)) just to make git happy ?
Michał Poreda almost 6 yearsIf you want to publish the rebased
featurebranch, the only way would be to force push it with
git push -f. However, be aware that you would be publishing rewritten history (in our example
E' are effectively "new") so if someone else has created commits on top of the old ones (D` and
E) they would end up in the same situation after a
git pull. So, if you can safely communicate to everyone who might have fetched
origin/featurethat you're about to push rewritten commits, you'd be fine. Otherwise, just don't rebase
featureand instead merge
John Cramerus about 4 years@EnricoCampidoglio I think this comment should be part of the answer. I read the answer and thought "Great, now I know why...but what's the best way to handle all these bogus commits?" I've been doing
git push -fto avoid infinite merge conflicts next time I rebase, but I hadn't thought of the case where someone else had been working on the branch and would have a copy of the old history.
endo64 almost 4 yearsAfter rebase I didn't force push my feature branch but I did
git pulland then
git push, does it break anything? Logs seem OK. There is no duplicate commits. Or I just did a merge commit after all?
PabloRosales over 3 yearsThanks, I was trying this but missing the last part
push --forceto the branch.
noelicus over 3 yearsMight it be clearer to say "bring in changes from the master branch"?
airborne over 1 year@EnricoCampidoglio: To be honest, I'm totally confused by your last drawing. Isn't the purpose of rebasing to put the feature branch on top of masters HEAD (F)? But now the feature branch is still branched of at commit C?
siliconrockstar over 1 yearDownvoted for 'avoid git rebase altogether'.
git rebaseis a useful tool that can be critical for effective devops, especially on large teams. Just because you don't understand how to use something properly doesn't mean you should tell other people to avoid it.
cmaster - reinstate monica over 1 year@siliconrockstar You did notice that I only proposed "avoid
git rebasealtogether" as an alternative? An alternative that I happen to like better, but still an alternative? I know that there are situations where you must use
git rebase. I've worked with both rebasing and merging, and I know why I prefer doing
git merge. Why do you think that it deserves a downvote that I advocate the better option (imho) a bit?
siliconrockstar about 1 yearBecause your opinion on what is the 'better option' is valueless. Depending on the use case, either option could be better or worse. Blanket opinions on how to solve non-specific problems get my downvote on principle.
r .r about 1 year@EnricoCampidoglio But now what happens if you rebase
master? You'll base
Michał Poreda about 1 year@airborne Running
git pull --rebaserebases the current branch on top of its corresponding remote branch, not
master. In this case, it would be the equivalent of saying
git rebase origin/feature.
Michał Poreda about 1 firstname.lastname@example.org Git is going to drop
featureon top of
Fcontains the same changes. The resulting history would look like this: