TheWaterProgrammer
TheWaterProgrammer

Reputation: 8269

Git rebase a branch on another after parent branch is merged to master

If I have branch_1 forked out of master with let's say 2 commits.

Next, I made branch_2 forked out of branch_1.
On branch_2 I have made changes which are not in the area branch_1. I of course have changes from branch_1 included here but I have not touched those changes.

Now let's say branch_1 merges into master.

Next, on branch_2 I do git pull upstream master --rebase to rebase branch_2 on top of master so that commits from branch_1 disappear from commit history of branch_2. I should not get merge conflicts here. Right? But I do in the same lines of code which were changed on branch_1. This is strange! Is this expected?

Upvotes: 1

Views: 5412

Answers (3)

IMSoP
IMSoP

Reputation: 97994

Your assumption about what the rebase would do is valid, if git knows the relationship between branch_1 and branch_2. Your problem is that you threw away that relationship by rebasing or squashing branch_1.

With a true merge, your commit graph would look like this (where "M" is the merge commit when you merged branch_1 into master):

            master
              |
              v
... <- A <--- M
        \    /
         <- B <- C
            ^    ^
            |    |
       branch_1 branch_2

Then, when you rebased branch_2 onto master, git would find that commit B is already reachable from master (as a parent of commit M), so wouldn't include it in the list of commits to replay.

However, when you squashed branch_1, you created this (where "BS" is the result of squashing branch_1):

            master
              |
              v
... <- A <--- BS
        \    
         <- B <- C
            ^    ^
            |    |
       branch_1 branch_2

Now when you ask to rebase branch_2 on master, it finds that commit B is not reachable from master (commit BS), so includes it in the list of commits to replay. If commit B was actually multiple commits, it will apply them one by one, and since the changes have already happened in BS, you'll get conflicts when it does so.

The solution (other than using true merges from now on 😛) is to be more explicit about what you want to rebase, by either:

  • Using an interactive rebase (git rebase -i upstream/master) and manually deleting the commits from branch_1 from the todo list
  • Using the three-argument form of git rebase, "rebase old_base old_tip --onto new_base": git rebase branch_1 branch_2 --onto upstream/master

Upvotes: 4

laker93
laker93

Reputation: 832

To rebase branch_2 from master, after branch_1 has been merged, do:

git checkout branch_2
git rebase branch_1 branch_2
git rebase --onto master branch_1 branch_2

Upvotes: 0

Medamine
Medamine

Reputation: 139

I have reproduced your situation like in the first image below.

Notice here I have the following naming :

master ==> main

branch_1 ==> br1

branch_2 ==> br2

And the br1 is merged into main

And the head is at the main branch (*)

enter image description here

To rebase br2 into main, you should :

git checkout br2
git rebase main

enter image description here

Upvotes: 1

Related Questions