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.
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).
- 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.
- 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.
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.
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.
- 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.
- 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.
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.
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.
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.
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.