Rebasing in Subversion

One of Git’s most popular features is the rebase command. Rebasing has several uses, but one of the most interesting is the ability to ‘merge without merging’. In other words, you can take a set of commits from a branch and reapply them to the same branch after adjusting the branch pointer. A couple of pictures will help to illustrate the concept as we try to keep a topic branch up to date with the latest work from master.

In this picture we start with a master branch, then make a topic branch and record a commit there. Next we switch back to master and record another commit. Then we merge master to topic to pick up the latest trunk work, and end up with a merge commit.

Rebasing lets us take a different approach.  

We start out the same way, but instead of merging master to topic, we rebase topic to master. That takes our local commit (t-1) and reapplies an equivalent patch after moving the topic branch to the head of master. The net effect is that it looks like topic was created from the current head of master. This is a really useful way to keep topic up to date with master without recording a bunch of merge commits.

It’s not possible to do this directly in Subversion, but there is a recipe that gets you close. First let’s look at the normal situation in Subversion when I work on a topic branch and do a refresh merge from trunk.

The revision graph (from SmartSVN) shows what you’d expect, although note that Subversion revision graphs don’t show the merge arrows.

Now let’s look at how to get to this point instead:

I can’t change my branch pointer in Subversion like I can in Git, but I can create a new branch (I’ll call it feature_prime) that starts from the new tip of master and then apply any patches from the original feature branch. At this point I can throw away the original feature branch and continue working on feature_prime. It’s not an ideal solution, but may still be useful in some cases.

How did I get there?  Here’s the recipe, starting after the m-2 commit on master:

# make feature_prime branch
svn copy ^/master ^/feature_prime -m "mkbranch"
svn up
cd feature_prime

# calculate diffs between feature and master
svn mergeinfo --show-revs eligible ^/feature ^/master

# for each rev found, run a cherry pick merge into feature_prime
svn merge ^/feature -c 8 --ignore-ancestry
svn commit -m "rb-8”

Essentially we find the deltas between feature and master, then run an ignore-ancestry merge to get them into the new branch. That type of merge ignores the normal merge history and just calculates diffs.

In my next post about rebasing in Subversion I’ll talk about the more general case of rebasing in Git, which turns out to be easier to emulate in Subversion.


4 Responses to “Rebasing in Subversion”

  • This recipe is incomplete in several ways:

    1. It omits the real-world situation where the branch is partially in sync with it’s parent, and dangerously merges ignoring ancestry. This only works if there are no sync merges in the branch. Better methods exists, as follows:
    2. The tree merge option for re-basing a branch is missing. (need to be in sync)
    3. The opton of re-basing using a trunk working copy, a merge from the branch and a copy/commit from there overwriting the previous branch is ommitted.
    4. You can actually rebase a branch and end up with a branch of the same name. Just delete the previous branch and use the PEG revision syntax to specify the deleted old branch as a merge source.
    5. You can perform the whole rebasing in one commit when using working copies of specified depth covering the root of the repository and the parent path where branches live.

  • Good points, Andreas. Rebasing is never a trivial operation and particularly so in Subversion, since the merge engine wasn’t really designed for it.

  • Absolutely. If you can, avoid rebasing. To that effect, prefer shorter lived feature branches created from trunk. Split your work into smaller identifyable chunks that can be coded, tested, brought back into mainline and potentially released. This works well with Agile methodologies.

  • Rebasing in subversion is only worth it if you have on repository for your framework and make only big changes on it. Such as transitioning from mysql to mysqli in php.

Leave a Reply