Last Updated: December 20, 2017
· koraktor

Rebasing dependent branches with Git

Git encourages you to use branches and depending on your workflow you might get pretty complex commit histories. Sooner or later you might also run into situations where you want to rebase a branch that itself has child branches.

Initial history:

master ---A---B---C
feature1    D---E---F
feature2              G---H

So you start rebasing feature1 on master:

$ git rebase master feature1

And the result looks like this:

master ---A---B---C
           \       \
feature1    \       D'--E'--F'
feature2      D---E---F---G---H

Doing another plain rebase of feature2 on feature1 might be problematic, because they share a similar, but not the same history. The commits D, E, F and D', E', F' will get you into trouble. Depending on the complexity of your branches and the number of commits this might be at least tedious to solve using git rebase --skip to skip the right commits. In the worst case you might mess up your code with unnecessary conflicts.

The solution is to use git rebase --onto after rebasing the first branch.

$ git rebase --onto feature1 feature1@{1} feature2

This will rebase all commits of feature2 that follow the old head of feature1 (i.e. F) onto the new head of feature1 (i.e. F'). The syntax feature1@{1} means "the last known state of feature1 before the rebase" and requires reflogging to be enabled (the default for non-bare repositories).

The command above should rebase feature2 on feature1 without problems and have the following result:

master ---A---B---C
feature1            D'--E'--F'
feature2                      G'--H'