Subversion 1.5 – Resolving Conflicts
If you are a regular reader of this blog then you are undoubtedly aware that Subversion 1.5 will be coming out later this year and that the big feature is merge tracking. Technically, merge tracking is a largely internal feature with the exception of the ways in which it simplifies the overall UI of the merge process. Implementing this feature has caused us to spend a lot of time just thinking about the entire merge process and this has led to some additional improvements that are not technically part of the merge tracking feature. That brings us to what this post is about and that is how Subversion 1.5 will make it easier than ever for you to resolve conflicts.
There are two specific enhancements that are coming in Subversion 1.5 that are related to resolving conflicts. The first is that the svn resolved command was enhanced to include a new –accept option that lets you mark a conflict as resolved by choosing a specific version of a file and the second is a feature we call interactive conflict resolution.
When Subversion generates a conflict in a file, you have to take some kind of action to resolve the conflict and then run the svn resolved command to tell Subversion that you did so. As stated previously, this command now has an –accept option that allows you to mark the conflict as resolved and also choose a specific version of the file at the same time. The most obvious use for this feature is with binary files.
An example where I know I will use this feature is when I have a release branch that is using a different version of a binary, such as a JAR file, than my trunk. For example, my branch might be using the 1.x version of some library and trunk is using 2.x. When I backport changes from trunk to the branch and I include revisions that updated the libraries, I get conflicts in my branch. Without this command, I would have to manually copy/rename the correct version of the file in my working copy, and then run the svn resolved command. With this enhancement, I can now just tell Subversion to do this for me. For example:
svn resolved –accept=left my-library.jar
This would resolve the conflict taking the version of the file that was already being used in the branch. Besides binary files, other users commented they would use this in scripts that are doing automated merges to certain branch types. Obviously this feature is not designed to deal with scenarios where you need to use a 3-way diff/merge tool to resolve the conflicts line by line. However, the next feature I want to talk about does cover that scenario.
Interactive Conflict Resolution
The development of the svn resolved feature really got the developers thinking about how this sort of feature could be integrated into the merge process itself (by the way: both of these features also apply to the update and switch commands as they can also generate conflicts). This led to the creation of the interactive conflict resolution feature. Here is an example of the feature:
Conflict discovered in 'contrib/client-side/svnmerge/svnmerge.py'.
Select: (p)ostpone, (d)iff, (e)dit, (h)elp : h
(p)ostpone - mark the conflict to be resolved later
(d)iff - show all changes made to merged file
(e)dit - change merged file in an editor
(r)esolved - accept merged version of file
(m)ine - accept my version of file
(t)heirs - accept repository's version of file
(l)aunch - use third-party tool to resolve conflict
(h)elp - show this list
Select: (p)ostpone, (d)iff, (e)dit, (h)elp : t
Updated to revision 25685.
In this example, I was running the update command and it encountered conflicts because I had local changes to a file that I needed to commit. The update process prompted me to resolve the conflict and also gives me a lot of different options to assist me. In this example, I took the (h)elp option to show some of the more advanced options that are available. For example, as with the svn resolved feature, I can choose to just select a specific version of the file (again useful for binary file types), but now I can also choose to see a diff, or open an editor or even launch a 3-way diff tool. The latter two options require an environment variable named EDITOR or SVNMERGE to be set with the tool to launch.
If you take the option to edit the file, when you are finished, you can just indicate to Subversion that you have resolved the conflicts. In this case, the file is never marked as conflicted in the working copy and does not need to be resolved later. Note that you can also just use the (p)ostpone option if you want Subversion to just mark the file as conflicted in which case you can resolve it later, as you would today.
There are a couple of ways you can turn off this feature. The first is to add the –non-interactive option to the command when you run it. With this option set, Subversion will just create conflicts and not prompt you during the process. This is useful for automated scripts or one-offs when you just do not want to be prompted. You can also turn this feature off globally by editing the runtime configuration file and setting this option:
interactive-conflicts = no
With this setting in your configuration file, you essentially have the pre-1.5 behavior.
Something I did not touch on yet is that both of these features are available in the Subversion API, so graphical clients will be able to easily implement the same features. For example, I have already integrated all of the interactive conflict resolution into the CollabNet Desktop – Eclipse Edition. As we get closer to the release date for Subversion 1.5, I will probably do another post that shows some of the features from the perspective of our graphical client for Subversion. Likewise, I am sure that TortoiseSVN will integrate these features soon and will do some great things with this.