Subversion‎ > ‎

Branching Strategies

If you are familiar with SCM systems that supports branching and merging such as Git, Mercurial or ClearCase you will probably also recognize the term developer stream/branch. The term is normally used to describe a private or isolated branch on which the developer can prepare his changes, and when he finds his work fit for sharing with his colleagues he then pushes/delivers it onto the project's integration streams. Hereafter he can continue to do more changes on the developer stream and deliver them later.

Here's a shot description on how to implement this development branching strategy work in Subversion.

Let's use the example that branching trunk to a developer branch in revision 80, then the developer is doing his work, and commit his changes to his own branch in what becomes revision  94. Now he would like to integrate his work onto the trunk and he merges it back there. The tricky part in Subversion is that merges are really pulls and not pushes. So out-of-the-box the trunk will know what happened (it pulled work from the developer branch) but the developer branch hasn't got a clue, that some of the stuff was delivered onto trunk.

This is a problem in Subversion. If you were in git, Mercurial or ClearCase, these systems would internally keep track of what had happened and then development stream would immediately be ready for continued use. In Subversion on the other hand you are instructed to regard the development streams as a -now terminated - feature stream and you should abandon it and create a new one.

If the developer now continues to work on his own branch in Subversion, and he makes a new commit - say 104. Then the next time the trunk pulls from the developer branch it will still merge all the changes from 80 through 104, even if the ones from 80 through 94 was already pulled once.

The trick is to make the development branch aware of the fact that revisions 80 through 94 has been pulled by trunk already, so that next time trunk pulls  the development branch only offers the succeeding changes.

The solution is that every time the trunk pull from a developer branch, the developer branch must pull changes back again - the term rebase is frequently used for this operation, only it's not very logical that you should rebase a branch that just delivered. But if you can accept this as an odd feature in Subversion and just live with it - it actually works.
As you can see in the picture to the right.
If you do not "rebase" (Fig. A) you will end up with delivering the entire change set every time, and effectively merge changes that has already been merged. But if you do the rebase (Fig. B) - that is merge trunk to the developments branch immidiately, then subversion is able to know the difference.


Create a new development branch off trunk and swith your work space

svn cp -m "dev branch" svn://server/trunk svn://server/branches/trunk/dev1
svn switch svn://server/trunk svn://server/branches/trunk/dev1

Make achange and commit it

mkdir b
svn add .
svn commit -m "Added a b directory"

Switch back to the trunk and pull the changes from the dev branch

svn switch svn://server/trunk
svn merge svn://server/trunk svn://server/branches/trunk/dev1
svn commit -m "pushed dev1 onto trunk"

Now switch back to continue work on the development branch

svn switch svn://server/trunk svn://server/branches/trunk/dev1

Here comes the very important solution to development branch unawareness to what has happened. You simply merge trunk into the development branch before you continue working.

svn merge svn://server/trunk

And now it's safe to continue using the development branch - as you would in git, Mercurial or ClearCase.

mkdir b
svn add .
svn commit
svn switch svn://server/trunk
svn merge svn://server/trunk svn://server/branches/trunk/developer_branchs
svn commit -m "Added a c directory"
svn switch svn://server/trunk svn://server/branches/trunk/dev1
svn merge svn://server/trunk