Upcoming release features automatic merge tracking -- finally! Branching and merging are two inherently related functions that are due for a long-awaited upgrade in Subversion 1.5. In this article John Ferguson Smart explains branching and merging in Subversion and shows you how these functions can scale from simple to complex as your code base evolves. He then introduces the new merge features to be introduced with Subversion 1.5, which will make tracking updates and resolving merge conflicts easier than ever in your rapidly changing code.Subversion is a powerful, open source version control system that has rapidly grown in popularity over recent years. It is well on the way to replacing the venerable CVS as the standard open source version control system. Indeed, since the release of version 1.0 in February 2004, the number of organisations adopting Subversion has grown at an impressive rate. In a recent informal poll, Subversion scored over twice as many users as CVS (and, incidentally, many times more than any of the commercial version control solutions).Subversion boasts many advanced features, such as atomic commits, versioned directories, good support for binary file formats, fast branching and tagging, and support for several network protocols, including HTTP. Subversion’s merge features have always lacked automatic traceability, however, making it difficult to find out after the fact what code was merged, where it was merged from, and when it was merged. Subversion version 1.5, in beta at the time of writing, brings many improvements in this area. Subversion 1.5 makes it easier to merge code from different branches and automatically keeps track of what merges have been performed. It also supports strong IDE integration with Eclipse. This article introduces merging and branching in Subversion 1.5.Merging and branching in SubversionBranching and merging are important elements of any version control system, and play a crucial part in any software development process. Branching strategies are many and varied, and it is important to get a clear idea of your chosen strategy right from the start of your project. Before looking at Subversion’s merge features, I’ll go through the common branching and merging strategies used today.Probably the most common approach to branching involves having a main development trunk where the bulk of the development work is done. Whenever a release version is ready, a separate branch is created for this release. For example, you might create a new branch whenever you released a new version of your application for acceptance testing or into production. You might also want to create a branch for a specific, non-trivial bug fix. Meanwhile, your cutting-edge development work would continue on the main branch. This setup allows you to make maintenance bug-fixes to the production version without having to release the latest unstable version of the code. You might also use branching to work on a major new feature or refactoring exercise that is likely to take some time, and may or may not be included in the next release. This way, work can be done in isolation, without compromising the daily builds for the rest of the application.You will eventually want to integrate changes made in a branch back into the main development trunk. For example, you might want to apply a bug fix made in the production branch to the development branch as well. Or you might want to integrate new features into your main code base, as shown in Figure 1.Figure 1. Branching allows you to gradually introduce new features into the main code base (click to enlarge)This approach is simple and robust, and suits a large number of projects. Another branching strategy, illustrated in Figure 2, involves placing only stable, production-ready code in the main trunk. Separate branches are created for development work on new versions or bug fixes When the code in a development branch is ready for release, it is merged back into the main trunk. This strategy arguably provides better support for larger teams, more complex projects, and parallel development efforts. Its downside is additional overhead in complexity and administration. Figure 2. Sometimes branching involves placing only stable, production-ready code in the main trunk (click to enlarge)The second strategy is obviously more complex than the first, and is overkill for many projects. As in many things, the best approach is the simplest one that gets the job done. Merging before Subversion 1.5Branching in Subversion is fast and efficient. When you create a new branch or a new tag in Subversion, you are actually creating a reference to the original version, which can be done very quickly indeed. Modifications are successively logged against this new version, leaving the original version unchanged.To create a new branch in Subversion, you simply use the svn copy command to create a copy of a directory in the Subversion repository. By convention, branches are placed in a repository directory called “branches.” For example, in Listing 1, I create a branch of the main trunk called “bug-fix-101,” presumably to fix bug number 101. Listing 1. Creating a new branch: bug-fix 101C:/>svn copy file:///e:/svn/repos/tax-calculator/trunk file:///e:/svn/repos/tax-calculator/branches/bug-fix-101 -m "Creating a branch to fix bug #101, which is a bit tricky" Branching and merging have always been supported in Subversion. In versions previous to 1.5, however, Subversion did not automatically track merges. No record was kept of what change sets were merged, when, and by whom. Instead, users were advised to use informative log messages to keep track of merges. For example, to merge all the changes from the previously created branch, you would do something along the following lines:Listing 2. Merging all changesC:/>svn merge file:///e:/svn/repos/tax-calculator/branches/bug-fix-101 C:/>svn commit -m "Incorporated fix for bug #101." Successively merging several bug fixes from a branch (for example, a production release branch), is a bit trickier. In brief, you would need to work out exactly which revisions to merge (using svn log commands and informative commit messages), and provide these revision numbers using the “-r” option, as shown here:Listing 3. Merging specific changesC:/>svn merge file:///e:/svn/repos/tax-calculator/branches/release-1.0.0 -r25:28 C:/>svn commit -m "Incorporated latest bug fixes from version 1.0.0." This approach obviously has its disadvantages. First of all, it relies on human intervention to keep the repository clean and well documented, which is not a good habit. Working out what revisions need to be merged is a painful and error-prone process at the best of times. And, because Subversion doesn’t know about what merges have occurred, little automation is possible in the merging process. As you will see, Subversion 1.5 makes all of this a lot easier.Merging in Subversion 1.5For this article, I will be using a Subversion repository containing a single Java project called, somewhat arbitrarily, “tax-calculator,” which is an API for calculating income tax. Note that, for the purposes of this article, the actual content of the project doesn’t really matter — if you want to follow along at home you can easily use your own project instead.The application’s main development happens in the trunk, whereas branches are used for specific releases. So the repository directory structure looks like this: + repos + tax-calculator + trunk + tags + branches The best way to get a feel for the new Subversion merging features is to work through a practical example. This example will be intentionally simple. See the Resources section for a more complex example of merging with Subversion 1.5, complete with a non-trivial history of merges.Check out the projectFirst of all, we check out the project from the main development branch, using a fairly standard approach:Listing 4. Check out the projectE:>svn co file:///e:/svn/repos/tax-calculator/trunk tax-calculator-dev A tax-calculator-devtax-calculator A tax-calculator-devtax-calculatortest A tax-calculator-devtax-calculatortestcom A tax-calculator-devtax-calculatortestcomjavapowertools A tax-calculator-devtax-calculatortestcomjavapowertoolstaxcalculator ... Checked out revision 20. In this example, we have already released two versions of our API into production: versions 1.0.0 and 1.1.0. A branch exists for each of these, as shown here: Listing 5. This application has two branches so farE:>svn list file:///e:/svn/repos/tax-calculator/branches release-1.0.0/ release-1.1.0/ To make things clearer, we have also checked out the latest production release into a separate directory called tax-calculator-prod:Listing 6. The production release is also checked outE:>svn co file:///e:/svn/repos/tax-calculator/branches/release-1.1.0 tax-calculator-prod ... Checked out revision 21. Make some fixesNow suppose we make some fixes to the production branch. This is done in the usual way, by correcting the source code and committing to the production branch. The following listing shows three successive modifications made and committed to the repository:Listing 7. Three updates to the production branchE:tax-calculator-prod>svn commit -m "Corrected the tax rates" Sending tax-calculatorsrccomjpttaxcalculatordomainTaxCalculator.java Transmitting file data . Committed revision 23. ... E:tax-calculator-prod>svn commit -m "Updated the tax rate calculation" Sending tax-calculatorsrccomjpttaxcalculatordomainTaxCalculator.java Transmitting file data . Committed revision 24. ... E:tax-calculator-prod>svn commit -m "Updated the tax rate calculator module." Sending tax-calculatorsrccomjpttaxcalculatordomainTaxRate.java Transmitting file data . Committed revision 25. Integrate the changesEventually, we want to integrate our changes back into the normal development branch. In Subversion, branches are merged using the svn merge command. In its simplest form, this means locating yourself in the working copy of the target branch (often, but not always, the main development trunk), and executing svn merge along with the branch you want to merge. So, here, we go to the development branch and merge the changes made on the release 1.1 branch: Listing 8. Merging the changesE:tax-calculator-dev>svn merge file:///e:/svn/repos/tax-calculator/branches/release-1.1.0 --- Merging r22 through r25 into '.': U tax-calculatorsrccomjpttaxcalculatordomainTaxCalculator.java U tax-calculatorsrccomjpttaxcalculatordomainTaxRate.java Now, if you inspect the log, you will find that Subversion has added a useful entry, including a comment concerning the merge we just performed. Just use the new “-g” option, and all will be revealed.Listing 9. SVN logs the resultsE:tax-calculator-dev>svn log -g ------------------------------------------------------------------------ r26 | john | 2007-12-28 22:49:36 +1300 (Fri, 28 Dec 2007) | 1 line Merged latest production fixes ------------------------------------------------------------------------ r25 | john | 2007-12-28 22:44:45 +1300 (Fri, 28 Dec 2007) | 1 line Result of a merge from: r26 Updated the tax rate calculator module. ------------------------------------------------------------------------ r24 | john | 2007-12-28 22:44:04 +1300 (Fri, 28 Dec 2007) | 1 line Result of a merge from: r26 Updated the tax rate calculation ------------------------------------------------------------------------ r23 | john | 2007-12-28 22:43:38 +1300 (Fri, 28 Dec 2007) | 1 line Result of a merge from: r26 Corrected the tax rates------------------------------------------------------------------------ r20 | john | 2007-12-28 21:43:56 +1300 (Fri, 28 Dec 2007) | 1 line Initial import ------------------------------------------------------------------------ Rinse and repeatWhat you’ve seen so far already greatly improves on Subversion 1.4, but it gets better. Imagine we now do yet another bug fix to our production branch, shown in Listing 9.Listing 9. Yet another bug fixE:tax-calculator-prod>svn commit -m "Fixed something else" Sending tax-calculatorsrccomjpttaxcalculatordomainTaxRate.java Transmitting file data . Committed revision 27. Back in the main development trunk, we also need to integrate this correction. To re-merge code from a branch in Subversion 1.4, you would need to carefully select the revisions to be merged. For example, in this case, we only want to merge revisions 26 and 27. To figure this out in Subversion 1.4, you would needed to carefully study the log files and try to work out what was done, and when. In Subversion 1.5, thanks to merge tracking, the Subversion repository already knows when you last did a merge. So, in this example all we need to do is to perform another merge from the production branch, using exactly the same options we used previously. Subversion will work out what needs to be done.Listing 10. Subversion works out the details of a mergeE:tax-calculator-dev>svn merge file:///e:/svn/repos/tax-calculator/branches/release-1.1.0 --- Merging r26 through r27 into '.': U tax-calculatorsrccomjpttaxcalculatordomainTaxRate.java In other words, the merge is now repeatable — you no longer need to run a different command each time you merge your changes from a branch into the trunk. This alone makes integrating changes from a production branch much smoother. It also makes automation and integration into the build process much easier.Merge conflictsThere are of course times when even the most automated of processes gets stuck, and Subversion merges are no exception. When you merge changes in from another branch, there is always the possibility that someone else has modified a section of code that you have also been working on. In this case, Subversion wisely lets you decide what version is correct. This is known as a merge conflict. Merge conflicts are handled more smoothly in Subversion 1.5 than in previous versions, making it easier to fix minor conflicts on the fly, rather than having to abandon the merge process. When a conflict occurs, Subversion proposes a number of options, including visualising the differences via the diff command, opening the conflicting file in a text editor, or postponing the correction (and thus the merge) to a later date. In Listing 11 we use the d option to view the differences in the two versions.Listing 11. What’s the difference?> <b>svn merge</b> Select: (p)ostpone, (d)iff, (e)dit, (h)elp for more options : <b>d</b> --- C:DOCUME~1johnLOCALS~1Temp/tmp Mon Dec 31 14:38:32 2007 +++ tax-calculator/src/com/jpt/taxcalculator/domain/.svn/tmp/tempfile .9.tmp Mon Dec 31 14:38:32 2007 @@ -1,8 +1,12 @@ package com.jpt.taxcalculator.domain; +<<<<<<< .working /** * A Tax rate. + * More stuff. */ +======= +>>>>>>> .merge-right.r23 public class TaxRate { private double minimumRevenue; Select: (p)ostpone, (d)iff, (e)dit, (r)esolved, (h)elp for more options : Once you’ve either visualised the modifications using the (d)iff option, or edited the conflicting file via the (e)dit option, a new option appears: (r)esolved. When you choose this option, Subversion will consider the conflict fixed, and move on to other things. Other convenient short-cuts are also available for more quick fixes, including (m)ine (“accept my version of file”) and (t)heirs (“accept their version of file”).The svn resolved method has also been improved to make resolving conflicting files easier.Subversion 1.5 has added the --accept option, which makes it easy to resolve a conflicting file and specify the file you wish to keep without resorting to file copying or renaming. The --accept option takes intuitive values such as mine (keep my file), theirs (use the other version of the file) or base (use the base version of this file in the local working copy). This is especially useful for binary files, as illustrated here. Listing 12. –accept makes it easier to resolve merge conflicts> <b>svn resolved src/web/images/logo.gif --accept=mine</b> Using Subversion 1.5 in EclipseOf course, not everyone likes using the command line. The new version of Subversion also comes well integrated with Eclipse, including a new merge feature built on top of the Subclipse plugin. See the Resources section to install this new plugin.Once you’ve installed the plugin, you can access the new merge client via the Team->CollabNet Merge menu. This opens a wizard-like interface that guides you through your merge in a fairly intuitive way. You can either opt for the standard merge interface, which keeps things simple, or the advanced interface, which gives you access to all the command-line options. This is a big improvement on the previous Subclipse merge menu, letting you perform common merges with virtually nothing but the source branch of your merge. The merge wizard is shown in Figure 3.Figure 3. The new Subclipse merge wizard (click to enlarge)This wizard guides you through the merge process. If there are any conflicting files, Eclipse proposes a number of options. You can choose to resolve the conflict directly or edit the file either manually or using a graphical conflict resolution editor, as shown in Figure 4. Figure 4. The graphical conflict resolution editor (click to enlarge)Not surprisingly, the History view (Team->History) now lets you visualise information about previous merges. You need to activate the option “Include merged revisions” to display merge history, as shown in Figure 5.Figure 5. Activating merge history (click to enlarge)Once you have activated merge history, you can also view details of a particular merge by selecting “Show Merged Revisions” in the contextual menu, as shown in Figure 6.Figure 6. The Show Merge Revisions screen (click to enlarge)In conclusionSubversion is a popular version control system that promises to overcome one of its main drawbacks with its upcoming release, Subversion 1.5. In this article you’ve seen how Subversion 1.5 makes it easier to handle branching and merging in your development projects. With Subversion 1.5, you can automatically keep track of the various merges that happen in your project. Merging changes from one branch to another is both smoother and more reliable. This in turn makes it easier to use branches and merges efficiently in your development process.It’s important to note that Subversion 1.5 is still in the final stages of development at the time of writing — there are still a few wrinkles to be ironed out, and using it in production in its current form is not recommended. The final release date for Subversion 1.5 has yet to be announced. Also note that merge tracking isn’t the only major new feature added to Subversion 1.5. The new version also adds change lists and sparse directories to Subversion’s feature set. Merge tracking is likely to be the major selling point for Subversion 1.5, however.See the Resources section to learn more about Subversion and other open source version control systems.John Ferguson Smart has been involved in the IT industry since 1991, and in Java enterprise development since 1999. His specialties are Java EE architecture and development and IT project management, including offshore project management. He has a wide experience in open source Java technologies. He has worked on many large-scale JEE projects for government and business in both hemispheres, involving international and offshore teams, and also writes technical articles in the JEE field. His technical blog can be found at https://www.jroller.com/page/wakaleo. Open SourceSoftware DevelopmentBuild AutomationJava