Friday, January 19, 2007

Enhanced Support for Branches and Tags in Subclipse

This post largely draws on content I previously wrote and posted on the Subclipse web site back in December 2005 when this feature was added to Subclipse. I have attempted to freshen the content a bit in some places and repost it here for a new audience that may not be aware of this feature.

The issue of tags in Subversion, and how they differ from CVS, is a frequent topic on the Subversion users@ mailing list. The same issue came up a lot on the Subclipse mailing lists, especially since the CVS plug-in in Eclipse handles branches and tags very nicely. The design for this feature evolved over time out of requests and suggestions from Subclipse users, along with a few niceties that I added while developing the feature when I realized I could use the information in additional ways. I was initially against adding the feature, as I generally try to stay true to the features of Subversion and do not like inventing concepts that are not really supported and backed by Subversion. However, in the end I really like the way this feature turned out, and I find it very useful in my own projects. There are some areas it could still be improved, but all in all, it is a nice feature.

In no way would I attempt to make the claim that this answers every request/idea/complaint that Subversion users have had about the way tags are handled. That being said, it does address a lot of them :)

In many ways, the support for branching and tagging in Subversion represents a vast improvement over CVS. It certainly addresses many of the complaints with this feature in CVS. There is one significant drawback in the implementation in Subversion. Namely, the process of creating a branch/tag does not leave behind any "breadcrumbs" in the source of the branch/tag operation to indicate that the branch/tag was created. In other words, there is information in the branch/tag that indicates where it came from, but there is no similar information in the origin of the branch/tag that would let you see or know that the branch tag exists. The net result is that when looking at a file or folder there is no easy way to know which revisions belong to which tags.

Subclipse provides a way for you to work around this problem by allowing you to maintain a Subversion property in your project that indicates the branches/tags that have been created from that project. The name of the property is subclipse:tags. The format of the property value is:

The above screen shot shows what the property looks like if you were to edit it directly. However, Subclipse also provides a Configure Branches/Tags option on the Team menu that allows you to edit the property using a custom editor.

Besides providing basic CRUD capabilities, the dialog also includes a built-in repository browser. This allows you to select one or more folders and add them as a branch/tag in one action. When folders are added in this manner, Subclipse automatically fills in the Revision number based on the Last Changed Revision of the selected folder.

In addition to the Configures Branches and Tags option, there is also support for automatically updating the subclipse:tags property when you create a Branch/Tag using Subclipse. When you take this option, if we detect the subclipse:tags property on the item you selected, then we pop-up a dialog that lets you confirm that you want to add this new information to the subclipse:tags property. You then just have to commit that property change after creating the Branch/Tag. This feature does not exist when creating the Branch/Tag from the repository browser as it is only possible to modify a property value in a working copy.

A nice aspect of using a Subversion property to drive this feature is that only a single user or build process needs to assume the responsibility of managing the property value. They just commit the property change and all users receive the benefits in their UI when they update.

Once the property has been defined, there are a number of ways that Subclipse takes advantage of it to provider a better user experience in the UI.

History Browsing
This was really the number one reason for pursuing this feature in the first place. The History View has been enhanced to show the tags for a revision.

When the History option is invoked against a local resource, we read the subclipse:tags property value from the local working copy and use its contents to populate the tags column in the view. A preference controls whether to show this information when browsing history directly from the repository. In this scenario, in order to show the tag information, we have to search the repository for the presence of the subclipse:tags property. On a slow connection you probably would not want to do this.

Compare Revisions
The Compare with Revision ... option has been enhanced to show tags in its history view. This makes it easy to know which revisions you want to compare.

URL Chooser
The URL Chooser that allows you to pick a URL in many of the Subclipse dialogs has been enhanced to show Branch/Tag information. This allows you to just select a branch/tag by it's name or identifier and the proper URL to that branch/tag will be automatically created. The enhancements we were able to make to this dialog turned out to be the best "side-effect" of adding this feature. Not having to type out, or browse to select, really deep URL's in the repository is a real time saver and usability improvement.

Compare with Branch/Tag
Technically this feature is not dependent on the property, but it was added at the same time and the property makes it easier to use. Subclipse provides a Compare with Branch/Tag option in the Eclipse Compare With menu. The option gives you the choice of producing a unified diff file or doing a graphical compare as shown in the screen shot below. The Eclipse graphical compare option can be fairly slow if you do not have a fast repository connection. Also, the Eclipse compare option will show differences in svn keywords which the unified diff option will not. That being said it is still convenient to have and combined with the enhanced URL Chooser, it is a very nice option.

In the future, I would like to enhance the graphical compare option to either be driven by a unified diff file (which would be much faster and accurate) or perhaps a new routine that used the new svn diff --summarize option to produce the initial list of differences, instead of letting Eclipse calculate them. Either option would make it run a lot faster and eliminate the false positives caused by the use of keywords.

Future Enhancements
Eugene Kuleshov has requested some enhancements to this feature that might come in the future.

The first is issue 471, which is to remove the revision number from the property value and instead just discover and cache it when needed in the UI. The reason he wants to do this is so that we can change the way we update the subclipse:tags property so that we do it before we create the branch/tag. Then the updated property information would be included in the new branch/tag. See this mailing list thread for his reasons.

I do have some concerns that this will unexpectedly slow down the UI when the cache is populated against a slow server. I suppose that could be solved with proper usage of a progress dialog, but I have the feeling this would happen so deep in the code that might be more difficult that it sounds. What I would ideally like to see is an ability to update the property in the branch/tag as part of creating it, but this would require new Subversion API support.

Eugene's next request was issue 472. This request is to enhance the create branch/tag process to allow you to process several projects at once. I would really like to see Subclipse focus on this area once the 1.2.0 release is finalized. Basically, we need to make it easy to perform all of the branch/tag options on multiple projects. This would include, creating the branch/tag, but also switch, merge and probably compare. This is also entered in issue 596.

This is a nice feature that improves the user experience for Subversion users. There is always more to do, such as better multi-project support, but we will get there.

The one negative I have found about this feature is that your branching policy will sometimes make it less effective. For example, the Subversion and Subclipse projects both have a policy where we create a branch, such as 1.2.x, to stabilize a release. All release tags are therefore made from the release branch, which means the subclipse:tags property, containing the tag information, lives on the release branch. However, developers mostly work in trunk and thus cannot really benefit from the History view feature of showing the tags in the view. This is an area where I think native Subversion support for knowing what tags a revision was copied to would be needed. If Subversion ever added this feature, it could likely tell that a file that was copied to a branch and then tagged is the same file that is on trunk. I guess the problem is whether Subversion can ever add a feature like this and still support the concept of "cheap copies" which is the foundation of the whole product.


Anonymous said...

Nice feature
Well done I really like this feature! Many developers already asked for that at most people that switched from CVS to SVN were complaining about that.

However I agree with the problem when using release branches, so that developers don't see the "tag" when working on trunk.
But what about to solve this in a most easy way:
All you need to do is show not only the tags in the revision history but also the branches. This way when you create a branch you define the subclipse:tags property on trunk with branch and later on when releasing the branch you define the property with tag on the branch.

This is far from perfect, but at least the user sees in the file history on trunk that the file has been branched and get a clue where to look for further information and probably get the tag information there.

All you need is another column in the histroy view, and no subversion support.


Gunnar said...

Will that integrate with the branch tracking working that is done for Subversion 1.5 or is it unrelated to that one?

Mark Phippard said...

I would say it is unrelated. Although I think if the feature were more fully ingrained in Subversion it might be possible to leverage it. Just like the basic problem described in the article, the merge tracking feature in 1.5, applies to the target of the merge. So you can track what you have already merged.

The place where you would need this info to know what branches it was merged to still does not have any info.