Login | Join Now

desktop-eclipse
Merge Client

Overview of CollabNet Merge Client

The CollabNet Merge Client has been built on top of Eclipse and Subclipse. This combination allowed us to support multiple client operating systems and also allowed us to focus on the actual merge client and merge process while leveraging the excellent Subversion capabilities that already exist in Subclipse. This gives you a powerful client that allows you to perform all Subversion operations from a single tool. Commit, History, Blame, Switch, Tagging. Everything you need is available. You do not have to be an Eclipse shop or even an Eclipse developer to use the client. Eclipse and Subclipse make it easy to checkout and access any project in your repository. You can just use the client as a general Subversion UI, or even just to perform merges. Adopting the client does not require that you adopt Eclipse as your only development tool.

The CollabNet Merge Client is also built on top of the merge tracking feature of Subversion 1.5 and requires Subversion 1.5 on the client.

The goal of the client is simple -- make merge easier. There were a couple of aspects to making merge easier. First, the Subversion 1.5 merge tracking features make certain kinds of merges much simpler as the user does not need to supply as much information to Subversion in order to perform a successful merge. So part of building this client was figuring out how to leverage this in the UI while still making it possible for a user to perform the more complicated merge scenarios. The second aspect to the development of the client was to just focus a lot of attention on the merge process itself and to provide the user with as much or as little assistance as needed to complete the merge process, which includes resolving conflicts and ultimately committing the changes to the repository.

For the purpose of this document, we will just walk through the merge process beginning to end and discuss the various features as they come up along the way. It might require reading through this a few times to catch all of the features that have been provided.

Performing a Merge

In order to perform a merge you must have a working copy that is pointing to the area of the repository that you want the merge results to be committed to. So to start the process you must first checkout a new project or update/switch an existing project in your Eclipse workspace. It is a best practice to not have any uncommitted changes in this working copy, and it usually a good idea to update the entire working copy to HEAD before beginning the merge.

Right-click on the project and choose Team > Merge. This will launch the CollabNet Merge wizard. We decided to adopt a wizard-based solution to the merge process for a couple of reasons. Most users are familiar with the wizard UI concept and it affords us the opportunity of sending the user down different paths in the UI based on the type of merge they are doing. This allows us to show or hide relevant aspects of the merge process based on their selections.

Note: The merge client is built on top of Subclipse, which has its own merge implementation.  You can set the merge input provider in the Subclipse preferences.  By default, the CollabNet Merge wizard, when installed, will be the default provider.  If you are not seeing the wizard then check the preferences under Team > SVN > Diff/Merge.

Select the Merge Type

The first page of the wizard asks you to specify the type of merge you want to perform. The merge client was designed to be extensible via Eclipse's plug-in mechanism. The screenshot shows the inputs that are available by default:

The terminology used to describe the merge inputs is based on the type of merge operation you want to perform.  Most merge scenarios would be covered by either the first or second option in the list.  The first option is designed to cover the scenario where you want to merge changes that have happened in the "branch source" to the branch.  This covers a lot of scenarios, such as synchronizing a feature branch with the changes that have happened in trunk, as well as selectively back-porting fixes to a release branch. 

The second merge input, reintegrate, is for merging the changes that have happened on a branch back to the "branch source" or trunk.  This would typically cover the scenario where you have completed the work on a feature branch and want to reintegrate the changes back to trunk.

The change set-based merge input is covered in its own document here

The last two merge inputs cover the scenarios of manually recording or removing merge information which can also be used to block or unblock revisions.

Select the first merge input and click Next.

Select the Merge Source

On this page of the wizard you are indicating what you want to merge. There are a couple aspects of this page that are leveraging the merge tracking feature:

  1. The "merge from" drop-down will contain a list of suggested merge sources. This is populated from the contents of the svn:mergeinfo property. The value will default to the last location you merged into the target location, or the location it was originally copied from if no merges have happened yet.
  2. In the revisions section, there is an "All eligible revisions" option. This is equivalent to running the svn merge command with no revision arguments specified. When this option is used, Subversion will merge all revisions in the from location that have not already been merged into the target.

Both of the above features require a Subversion 1.5 server to work properly. For example, if the server is running 1.4 then only the location the target was copied from will appear in the combo box (or just the location itself if it was never copied). Likewise, the All eligible revisions feature will not work as expected if the server is not running 1.5. In that scenario you can still use the option to select specific revisions, which is similar to what you would do today.

The "All eligibile revisions" feature would be useful if you are doing something like merging all changes that occurred on trunk since a branch was created or last synchronized with trunk. If you selected the "All eligible revisions" option you would essentially be done and could click Finish or Next to go to the last page of the wizard. For the sake of explaining all of the possible wizard pages, I will assume you chose to select specific revisions.

Before moving on, I just want to point out a small feature we added to make the process a little easier. Note in the above screenshot that the UI does not require you to enter URL's. You can enter paths that are relative to the repository root, and the client will convert those into URL's for you. Of course you can still enter a full URL, but this was just a simple feature we added to make the client a little easier to use.

Select the Revisions

This page will list all of the revisions that are eligible to be merged.  When talking to a 1.5+ server, it will filter out any revisions that have already been merged into the target.  A nice feature of this page is that it should be clear to the user that they are selecting the specific revisions they want to merge. They do not need to be confused with the underlying syntax it requires to merge those revisions. In addition, the wizard allows you to select non-contiguous revision ranges. You do not have to merge an entire range of revisions, you can omit some revisions.

We will assume you selected some revisions and clicked Next to see the last page. However, note that the Finish button is also enabled. We do not want you to have to visit the last page of the wizard unless you want to.

Select Merge Options

This final page of the wizard is common to all merge inputs, so the wizard will always end with this page. As mentioned earlier, the Finish button is always enabled before you get to this page. If you do not visit the page, then default values will be used. The defaults are explained below.

This page has two sets of options on it. The first part contains some standard options that are available on the merge command (--ignore-ancestry, --force and --depth). These always default back to what we believe are the most common and sane defaults as shown above. The second part contains options for how you want to handle conflicts, which you are more likely to want to change, so we remember the last values you used for these options.

The conflict handling options will be explained in more detail later. Hopefully, they are fairly self-explanatory. Essentially, you can now ask to be prompted during the merge process to resolve conflicts as they occur, or use the default behavior of creating conflicts in the workspace and resolving them after the merge completes. A nice feature is that we allow you to specify different options for binary files. So maybe you are merging a change to your web design into trunk and you know if there are any graphics conflicts you just want to take the version you are merging in. We let you do that with an option up front so that you do not even have to be asked what to do.

That is it. Click Finish to perform the merge. The rest of this document will cover the features we have added to help you while the merge is running and after it completes.

The Merge Results View

Once the merge begins, it does not matter which wizard option you used, they all use the same merge process the rest of the way. For now, let's set aside the option of being prompted to resolve conflicts. We can come back to that later.

When we designed this client, one of the main things we wanted to do was make it real easy to understand what the merge process did, and let you work with those results. To meet those objectives, we created a special view for working with the merge results -- the Merge Results view. If you have used Eclipse you will notice this view looks and behaves a lot like the Synchronize view. That was on purpose as we modeled our view on the Synchronize view. We decided to create our own view rather than use the Synchronize view for a few of reasons:

  1. Simplicity. The Synchronize view API's are fairly complex and we did not want to spend forever debugging problems where we did not understand the API or it did not work quite the way we wanted it to.
  2. Features. There are some features we implemented in this view, and possibly more we have not yet, that we did not think we could implement in the Synchronize view. We did not want to get the Synchronize view working well only to later realize we would have to scrap it.
  3. Properties. This view makes an attempt to show changes to Subversion properties. We think this would have been difficult to do in the Synchronize view.
 

Anyway, we decided to create our own view and model it as closely as possible on the Synchronize view and its features and usability. In the screenshot you can see that it is very easy to see the changes that were made by the merge, including adds, deletes and conflicts. The view offers two presentation modes, flat and collapsed folders. The screenshot shows the collapsed folders presentation after using the Expand All option. The view also has a toolbar button to toggle between showing just conflicts or all changes. After performing a really large merge, this toggle makes it very easy to find and focus on the conflicts.

Working with the View

One feature we decided was very important was that the contents of the view had to be persistent. In other words, you might do a really large merge with tens or hundreds of conflicts that will take several days to resolve. It was important that the contents of the view still be there when you close and restart Eclipse each day. Consequently, you have to manage the contents of this view. When you are done with a merge and ready to commit the changes, you should take the option to remove the result from the view. The view can contain the results from many merges at the same time. Here are a few more features of this view (in no particular order):

  • All of the normal Eclipse and Subclipse editing options are available.
  • If you double-click on a file we launch the compare editor or the edit conflicts option depending on the current state of the file.
  • We extended the Subclipse edit conflicts feature to support custom conflict resolution programs by file type. So you could use the built-in Eclipse editor for some file types, WinMerge or some other external tool for other file types, and even a custom script to resolve conflicts in something like a Microsoft Word document.
  • One of the features we wanted to implement in this view that we did not think the Synchronize view could handle well, was "skipped" files. The Subversion merge process will often skip a file for various reasons. Usually you did something like delete the file in a branch and when merging changes from trunk, any changes to that file are skipped. When running the Subversion command line, this is just a message that goes to the console. If you do not see it, you do not know it happened. The merge results view shows anything that was skipped using a grayed out font. We then provide two special options on these types of items (remember they do not exist locally).
    1. You can examine the history of the item in the merge source. This lets you see more information about the item which might lead you to decide that you want it back in your branch.
    2. A copy option was added that does an svn copy URL WC command to create the item in your working copy by copying it from the merge source. This allows you to put the item back in your branch if you want it.
  • Finally, this view contains a special "Mark Resolved" option you can use after resolving conflicts. This will show the item with a special resolved check-mark decorator in the view. The item will still show in the filtered list of conflicts. Normally, once you resolve a conflict in Subversion the file now just shows as a file with local modifications. There is no way to know that it originally had conflicts. So this feature lets you track your progress in resolving conflicts as well as remember all of the files that had conflicts in the first place.

Merge Previews

Another feature, really more of a concept, we felt was important to implement was a merge preview. The design of Subversion and its merge feature does not easily accommodate a feature like this. We could have used the merge --dry-run option to populate the merge results view, but there is no way to reliably show you the details of what would have been merged. In other words, there is no way to show a 100% accurate graphical compare if the user wants to see one. Also, from a performance standpoint, a --dry-run merge does everything that a full merge does except write the final file to disk. So there is no performance advantage to using --dry-run.

The Subversion developers we talked to about this felt that the best way to see what a merge was going to do was to just run the merge. This lets you see exactly what happens as well as gives you plenty of tools for examining the results. If you really only wanted to preview the results or you decided that you do not want to do the merge, you can just run revert and discard the results. That is the approach we decided to take, but with some features to make it easier. If you want to preview a merge, you just do the same thing you would do if you were going to do a real merge. When the merge completes you can work with the results as you normally would. When you are done, we have added a special "Undo merge" option on the merge result node in the view. This option launches a wizard which recursively reverts all changes in the working copy, and then follows that up with a secondary process that lets you remove any files that are unversioned. This is because if the merge process added files, the Subversion revert option will not delete them. So the undo merge option cleans up the working copy. In addition, since we know that we want to revert the entire working copy, we just do a recursive revert which runs considerably faster than the normal revert option used in Subclipse.

In the end, we were very happy with how this feature worked out and think it does the job well. It is very important that you do not have any local uncommitted changes in your working copy before doing this. If you do, the Undo merge feature will remove them when it cleans up your working copy.

Resolving Conflicts

One of the most difficult parts of any merge process is manually resolving the conflicts that cannot be automatically merged by the tool. The Subversion merge process does a good job automatically merging most changes, but there are always going to be certain changes it cannot automatically merge. There are a number of things we have done in the merge client to make this process easier for you. Let me first go back and cover two features that were already discussed.

  1. On the final page of the merge wizard you are given some options on how to handle conflicts. The default out of the box is to just let Subversion record the conflicts in the working copy so you can resolve them later. If you already use Subversion, then this is how it works today with Subversion 1.4. We also allow you to be prompted during the merge process (which is what the rest of this section will cover). Finally, for binary files only, we allow you to tell us before the merge starts that you want to take a specific version of the file. Most binary files cannot be merged anyway, which means you resolve most conflicts by taking a specific version of the file. This lets you just do that up-front so that you do not even have to be asked during the process.
  2. The merge results view has a toggle that allows you to focus on the folders and files that have conflicts and then it also has a visual indicator that shows you which conflicts you have resolved. Essentially, it allows you to more easily manage the process of resolving the conflicts.

As mentioned, the other option that we provide is to allow you to be prompted to resolve conflicts during the merge process as the conflicts are encountered. When this feature is enabled and you run into a conflict, you receive a dialog like this:

As you can see, there are several options available. You can just let Subversion mark it as a conflict and deal with it later. You can also choose to resolve the conflict by just selecting a specific version of the file. This feature is most useful for binary files, but it can sometimes be useful for text files too. Finally, there are also two options for resolving the conflicts manually. One is to open the file in an editor with conflict markers inserted. The other option is to use a graphical conflict resolution tool. Eclipse includes such a tool and that is used by default, but you can also configure the client to use an external tool such as TortoiseMerge, WinMerge etc. As mentioned earlier, you can even configure a different tool based on the file extension. When you take this option, we just open the conflict resolution tool that you have configured for this file type, or the default if you have not configured a tool.

The details of actually resolving the conflict fall upon you. When you are done, if you made changes you want to preserve you need to save the file using the editor and then close it. You are then presented with this dialog.

This dialog allows you to tell the client if you actually resolved the conflicts. You might have taken a look at the code, realized it was going to be more complicated than you expected, and just decided to resolve it later. In that case, just cancel the editor and give the appropriate answer in this dialog. The merge process will resume at the next file and possibly prompt you again as it encounters more conflicts along the way.

Resume Merge Process

The merge tracking feature in Subversion 1.5 introduces some new scenarios that you could not get with earlier versions. Suppose you tell Subversion to merge All eligible revisions. Let's assume you made a branch at r100, merged a specific change from trunk (r150) and trunk is now at r200. The "All eligible revisions" option will break this merge up into two parts. First it will merge r100:149 then it will merge r151:r200. I like to refer to these as "merge passes" but I do not believe it has an official term. Anyway, suppose the first merge pass creates some conflicts, and you choose not to resolve them as part of the merge process. When this happens, the Subversion merge process has to abort at the completion of that pass. The reason it needs to do this is that it is possible that the merge of the next pass will require merging into those same files that currently have conflicts. There would be no way to do this reliably, so instead the process aborts so you can resolve all of the conflicts and then resume the merge process where it left off.

The CollabNet merge client manages all of this for you.

Let's start when the merge process aborts at the end of a pass. Remember, it will do this when conflicts are completed during a merge pass, and you did not use the interactive resolution feature to resolve the conflict during the merge. As an aside, let me also just point out that most merges will not involve multiple passes and will therefore not run into any of this. Back to the story, let's say the merge process aborts. You will get a dialog that looks like this:

The dialog shows you all of the files that have conflicts as well as the message that Subversion produced. The message will tell you information about the pass it was working on when the merge aborted.

After you click OK, you need to resolve the conflicts. The merge results view gives you a special indication that shows you that this merge aborted early as you can see in the screenshot to the right.

You need to go through the conflict resolution process for each file and as you finish with each file use the Mark Resolved option on the right-click menu.

Eventually, you will use the Mark Resolved option on the final file that had conflicts remaining. When you do, you will get a dialog like this:

This dialog tells you that you completed resolving the conflicts and asks if you want to resume the merge process. Just click OK and it will be resumed where it left off. If you choose not to resume the process when the dialog comes up (maybe you want to go home for the day) you can right-click on the merge result and a Resume merge option will be enabled to start the process. This entire cycle could repeat several times if your merge involves many passes and there are unresolved conflicts after each. Eventually you will get to the end of the cycle and the merge will complete. At that point the icon in the merge result view will go back to normal and the cycle will end.

Summary

This document contained a lot of information. Print it out and read through it a few times. It might also help to look back at it again after having used the client for a while. The goal of the client was to make merge easier. This client is definitely a step in the right direction. It allows you to tap into the ease of use (and power) provided by the Subversion 1.5 merge tracking feature. At the same time, we took a look at the merge process in general and looked for ways to make it easier for you to manage and understand. Hopefully you will try this client out and find it helpful.

Finally, please read this document on Additional features of the merge client to learn about some other features we are providing which are not covered in the above document.