denise
denise

Reputation: 159

Rebase a feature branch onto a specific commit of another branch

I am trying to rebase a feature branch (branched off of master) onto a specific commit of another branch. My initial status was the following

       C -- D            branch1
      /     
A -- B -- E -- F         master
                \
                         branch2 (zero commits after creating the branch)

I first rebased branch2 onto A in master which worked fine. My current status should (according to my understanding) be the following

       C -- D             branch1
      /
A -- B -- E -- F          master
 \
  B -- E -- F             branch2

I verified that branch2 branches off of master at commit A and is even with the master branch. What I now want to get is this

A -- B -- E -- F          master
 \
  B -- E -- F             branch2
   \
    C -- D                branch1

I tried

git checkout branch1
git rebase --onto B branch2

But this resulted in a whole bunch of conflicts and I don't understand at all how these arise. Maybe I am misunderstanding entirely what rebase does?

Note: After successfully rebasing branch1 onto B of branch2, I intend to reset master to A, so the final version is supposed to look the following way.

A                  master
 \
  B -- E -- F      branch2
   \
    C -- D         branch1

Upvotes: 3

Views: 1105

Answers (1)

Schwern
Schwern

Reputation: 164659

There's some problems with your assumptions. First, branches are just pointers to commits. You start with this, and master is checked out.

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

After git branch branch2 you have this.

       C -- D      branch1
      /     
A -- B -- E -- F   master & branch2

Note there is no stub branch, master and branch2 both point at F. Aside from their names, they are indistinguishable.

Once you checkout branch2 and git rebase A nothing changes. branch2 already has A in its ancestry, it remains pointing at F. You should have gotten a message like Current branch branch2 is up to date.

When you did git checkout branch1 and git rebase --onto B branch2 this confused things. There's an assumed third argument, the currently checked out branch. What you actually ran is git rebase --onto B branch2 branch1. That says "take the commits reachable by branch1 but not by branch 2 (the same as git log branch2..branch1 or C and D) and put them onto B". This should be a no-op, but if branch1 and branch2 have any changes in common the rebase will throw them out.

If C and E made the same changes you'd wind up with this, and probably a conflict.

       C -- D      original branch1
      /     
A -- B -- E -- F   master & branch2
      \
       D1 branch1

This doesn't make much sense, but that's what happens when you try to rebase between two cousins.

Also note that the rebased branch has the id D1, not D. Commit IDs incorporate the ID of their parents, so the ID must change. rebase does not rewrite history, it creates new history and tells you that's how it always was. A subtle but important distinction. Your original commit is still there... for a while.


If you want to go from this:

       C -- D      branch1
      /     
A -- B -- E -- F   master & branch2

To this.

A                  master
 \
  B -- E -- F      branch2
   \
    C -- D         branch1

That can be flipped over so it aligns with what you have better.

       C -- D      branch1
      /     
     B -- E -- F   branch2
    /
   A               master

All you need to do is move master to A. There's several ways to do this, one is git branch -f master A. This forces master to move to A.

Upvotes: 4

Related Questions