Search code examples
gitrebase

Rebase two branches onto another branch


Given the following git history:

enter image description here

What would be the simplest way to rebase branches feature/1 and feature/2 onto master to achieve the following history:

enter image description here

So far I have come up with the following:

  1. Checkout feature/2(head of the commit chain I want to rebase)
  2. Rebase the branch onto master: git rebase master
  3. Change the head of the feature/1 branch: git branch -f feature/1 <hash>

Where <hash> is the hash of the duplicated Feature 1 commit created by the rebase command.

It works fine but seems too complicated to me.


Solution

  • The simplest and quickest solution is the one you've already worked out. You can combine steps 1 and 2

    git rebase master feature/2
    

    and you might find it easier to avoid dealing with commit ID's, in cases (like your example) where it's easy to calculate an expression for the target commit

    git branch -f feature/1 feature/2^
    

    You could, as others mention, use two rebases. However, this is not simpler. That is to say, whether the sophistication of the commands is simpler is a matter of opinion; but what you're telling git to do is objectively more complicated. And as a consequence of that, there is more opportunity for things to go wrong. The specific technique of rebasing feature/1 first, and then rebasing feature/2 over feature/1, for example, relies on detection of duplicate patch ID's during the 2nd rebase, which will fail in unfortunate ways if any conflict resolution occurred during the 1st rebase. If you really want to use a 2-rebase approach, I would recommend the 2nd rebase be done as

    git rebase --onto feature/1 feature/1@{1} feature/2
    

    as this avoids even considering re-rewriting the feature/1 commits. (The feature/1@{1} is a reflog entry that points to feature/1 before it was rebased.) But then you're using less-common rebase syntax, which as far as I can tell is at least as "not simple" as what you were doing in the first place.

    Alternately you can use --fork-point to tell git to automatically interpret the reflog and try to figure out which commits would be dups.

    git rebase --fork-point feature/1 feature/2
    

    As long as you're doing both rebases at nearly the same time on the same clone, this will work most of the time. But it is adding more complexity (in the form of "magic" that git does under the hood), so you'd need to understand that it can go wrong, and if it does either (a) know enough about what it tried to do to diagnose the issue, or (b) back out and use one of the other methods.