Using FileMerge as a diff command for Subversion

Subversion principally uses the copy-modify-merge versioning model to allow parallel collaboration on the same set of files. For this to work well, it is crucial to have good tools to view and merge the differences between files.

The built-in diff and diff3 tools (from diffutils) go a long way to provide this functionality for text files on the command line. They do have some limitations though, including:

  • Worthless to find interline changes in long lines
  • Output of diff can be hard to read
  • No interactive merge support

Apple's Developer Tools for Mac OS X include FileMerge, a graphical tool to compare and merge files. FileMerge can be much handier to use, unfortunately, it doesn't integrate with Subversion straightforwardly. It can be opened from the command line with the opendiff command, but its interface differs from that of diff and diff3. It returns immediately (i.e. it forks and does not block) and it expects different arguments. Some wrapper scripts are thus required to call FileMerge from Subversion.

FileMerge in action

Wrapper scripts for FileMerge

Bash scripts for this task can be downloaded (or checked-out) from this link.

Three scripts are provided: fmdiff, fmdiff3 and fmresolve. They are described below. The location of FileMerge is hardcoded at the top of the scripts, check if this matches with your setup. Afterwards, you can do the following to install them in /usr/local/bin:

$ sudo make install

fmdiff

fmdiff has an interface similar to diff and can be used with Subversion's --diff-cmd option. The canonical case is:

$ svn diff --diff-cmd fmdiff <other diff options, files or URLs>

Subversion will start FileMerge for each file with differences. It will wait for you to quit FileMerge to clean up and show the next file (if any). The script cannot show the labels from Subversion in FileMerge. As a resort, it will print these on the command line:

Starting FileMerge...
Left: lock.c (revision 14670)
Right: lock.c (revision 14675)

fmdiff3

Unsurprisingly, fmdiff3 is the diff3-equivalent of fmdiff. It can be used with Subversion's --diff3-cmd option.

diff3 will merge the changes from two different versions that have a common ancestor. It is used by Subversion on an update (to merge changes from the repository with local changes) or a merge operation. Suppose that you have made local changes in a working copy and that meanwhile the repository was updated. To merge your local changes with those of the repository in FileMerge, do:

$ svn update --diff3-cmd fmdiff3

Note: By using the ancestor information, diff3 can merge the changes automatically, provided that there are no conflicting changes. The standard diff3 merge is therefore non-interactive. If conflicts do occur, they are marked in brackets, and Subversion expects you to resolve the conflicts later on, after the (partial) merge. fmdiff3, in contrast, does the merge interactively and completely. First, It will fire up FileMerge with the relevant ancestor information, and FileMerge will merge the non-conflicting changes by itself on startup. fmdiff3 then expects that you complete the merge by resolving the conflicts through FileMerge's facilities. When you save the merged version and quit FileMerge, the result is given back to Subversion as a completely merged version. So the conflict state is not needed anymore.

FileMerge interactive merge with conflict

fmresolve

Whereas fmdiff3 can be useful when you anticipate conflicts during an update or a merge, it's sometimes unpractical that you have to decide to use FileMerge a priori. When you did a standard update or merge using the built-in diff3, and you are faced with one or more files in conflicting state, fmresolve allows to use FileMerge a posteriori to resolve the conflicts.

$ fmresolve <conflictfile>

This will start FileMerge with the appropriate versions and ancestor to reinitiate the merge. Non-conflicting changes are resolved automatically at startup; you can then resolve the remaining changes. After you save and quit FileMerge, you can signal to Subversion that the conflicts were resolved:

$ svn resolved <conflictfile>

Permanently using FileMerge

You can configure the fmdiff scripts to be used permanently, by setting the options diff-cmd and diff3-cmd in the “editors” section of the runtime config file (i.e. ~/.subversion/config). After this change, you no longer have to include the –diff-cmd and –diff3-cmd options when invoking Subversion.

More info: Subversion Book - Runtime Config Area

Feedback?

Send comments and bugs to Bruno De Fraine.

 
internal/fmdiff.txt · Last modified: 06/12/2007 18:58 by bdefrain
 

© 2003-2010 • System and Software Engineering Lab • Submit comments and bugs to our Bugzilla or to the webmaster