5

I started working on branchB. Which was branched off from branchA. After a few weeks, the mainline branch develop have had a lots of commits merged in. Both branches A and B are way behind.

--d1--d2--d3  ...2 weeks later...  --d253  develop
       \
        a1--a2--a3                         branchA
                   \
                    b1--b2--b3             branchB (current)

I would like to keep up to date with the develop branch. And prefer to rebase my branchB off develop at its latest commit d253. Also all commits from branchA should be ignored. This will avoid me a huge effort of resolving merge conflicts (there are a lots). Because I am not the maintainer of that branchA. I can recreate in my branchB the dependecies I need from A. Not sure if I should do that before or after the rebase.

--d1--d2--d3  .....  --d253  develop
       \                  \
        a1--a2--a3         \
                            \
                             b1'--b2'--b3'

Q1. Is it correct to do

git checkout develop
git pull
git checkout branchB
git rebase --onto develop branchA

Q2. Let's assume the number of conflicts is quite important, about 30 files. Is rebase still a good approach compared to git merge develop ?

Polymerase
  • 6,311
  • 11
  • 47
  • 65

2 Answers2

3

Q1 - Well, it is the command that does what you show in the picture, yes. And if branch b is orthogonal to branch a, I suppose that's fine. I would hesitate to do this; is there a reason you don't want to rebase both branches up to a current d commit?

Q2 - I haven't noticed that rebase vs. merge makes much difference in terms of conflict resolution. The big difference would be that with the specific rebase you specified you would not include the a changes; which means if an a change conflicts with a d change you don't have to deal with it. (If a b change overlaps an a change, I don't think this will be noticed as a conflict per se, but it could well result in code in a broken state.)

The real question is, have the b commits been shared with other developers? If so then rebasing them away is not generally recommended as it creates problems for the other developers.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • branchB is not yet shared with other developers. Can you please explain the meaning of "if branch b is orthogonal to branch a"? As for "a reason I don't want to rebase both branches up to a current d commit?" this is b/c I don't maintain branchA. And it turns out it is a slow moving branch, the day it will be merged into the mainline is far. My branchB is more active and the few dependencies I needed from A could be cherry picked from A or I can even recreate some stubs to get my code working while waiting for branchA to merge in the future. Hope this is a good reason for rebase. – Polymerase Mar 21 '17 at 16:38
  • `rebase` vs `merge` I do notice a difference when `rebase` is "catching up" with long chain of commits. A file could have 5 conflicts when rebase replays this file on the history of the target branch. And requires conflict resolution 5 times. With merge, there is one final merge conflict step where all files are presented in one screen (I use IntelliJ). Each conflicted file only needs to be resolved once. Saying so, this doesn't mean that `merge` is better. I quite like rebase putting my changes on top of the target instead of a merge commit. Just want to know better the good practices. – Polymerase Mar 21 '17 at 16:52
  • By "orthogonal" I mean if your changes could've been made to the base development line independently of `a`, and vice versa. And from what you've said that's not the case. If you do decide to proceed (say by cherry-picking what you need from `a`) it likely will lead to more merge conflicts later; so you'll have to decide if that's worth it. – Mark Adelsberger Mar 21 '17 at 19:03
3

In order to rebase branchB on develop with ONLY the commits from B. Must use rebase --onto with 3 arguments:

git checkout branchB
git rebase --onto develop branchA branchB

Thank you to Git Tip of the Week: Rebasing Revisited Section "Rebasing onto" give an example which is similar to the scenario described in this question.

Also in git-rebase documentation. Reproduced here for convenience:

First let’s assume your topic is based on branch next. For example, a feature developed in topic depends on some functionality which is found in next.

o---o---o---o---o                  master
     \
      o---o---o---o---o            next
                       \
                        o---o---o  topic

We want to make topic forked from branch master; for example, because the functionality on which topic depends was merged into the more stable master branch. We want our tree to look like this:

o---o---o---o---o             master
    |            \
    |             o'--o'--o'  topic
     \
      o---o---o---o---o       next

We can get this using the following command:

git rebase --onto master next topic
Polymerase
  • 6,311
  • 11
  • 47
  • 65
  • The last argument in the `rebase` command you suggest is not needed; it merely says "checkout `branchB` before starting", and you've already preceded the command with an explicit `checkout` of branchB – Mark Adelsberger Mar 23 '17 at 13:23
  • @MarkAdelsberger Thanks, the default value of the 3rd argument is confusing. When does the 3rd arg means "checkout the branch in 3rd argument" and when does it means "up to this commit in current branch" ? As shown in [I can't understand the behaviour of git rebase --onto](http://stackoverflow.com/questions/29914052/i-cant-understand-the-behaviour-of-git-rebase-onto#29916361) from Enrico Campidoglio's answer, section "The Surgeon: git rebase --onto with 3 arguments" – Polymerase Mar 23 '17 at 13:41
  • 1
    Eh? Well, I guess it's a matter of interpretation, but the thing to understand is that the 3rd argument is a commit identifier (not necessarily a branch) and it **always** means "check out the 3rd argument". If the 3rd argument is `HEAD^^` (or some other reference to a commit on the branch but not at the branch tip), then this has the effect of saying "up to this commit", but it's still done by checking out that commit to start the rebase (and still would be unneeded if you check out the commit manually first; it's just syntactic sugar). – Mark Adelsberger Mar 23 '17 at 14:03
  • @MarkAdelsberger Reran a simulation and confirm that you are right. The 3rd argument (the branch to be rebased) can be omitted if it is already checked out. – Polymerase Mar 26 '17 at 03:13