Using External Differencing and Merge Tools

The interface between Subversion and external 2- and 3-way differencing tools harkens back to a time when Subversion's only contextual differencing capabilities were built around invocations of the GNU diffutils toolchain, specifically the diff and diff3 utilities. To get the kind of behavior Subversion needed, it called these utilities with more than a handful of options and parameters, most of which were quite specific to the utilities. Some time later, Subversion grew its own internal differencing library, and as a failover mechanism, the --diff-cmd and --diff3-cmd options were added to the Subversion command-line client so users could more easily indicate that they preferred to use the GNU diff and diff3 utilities instead of the newfangled internal diff library. If those options were used, Subversion would simply ignore the internal diff library, and fall back to running those external programs, lengthy argument lists and all. And that's where things remain today.

It didn't take long for folks to realize that having such easy configuration mechanisms for specifying that Subversion should use the external GNU diff and diff3 utilities located at a particular place on the system could be applied toward the use of other differencing tools, too. After all, Subversion didn't actually verify that the things it was being told to run were members of the GNU diffutils toolchain. But the only configurable aspect of using those external tools is their location on the system—not the option set, parameter order, etc. Subversion continues throwing all those GNU utility options at your external diff tool regardless of whether or not that program can understand those options. And that's where things get unintuitive for most users.

The key to using external 2- and 3-way differencing tools (other than GNU diff and diff3, of course) with Subversion is to use wrapper scripts which convert the input from Subversion into something that your differencing tool can understand, and then to convert the output of your tool back into a format which Subversion expects—the format that the GNU tools would have used. The following sections cover the specifics of those expectations.

Note

The decision on when to fire off a contextual 2- or 3-way diff as part of a larger Subversion operation is made entirely by Subversion, and is affected by, among other things, whether or not the files being operated on are human-readable as determined by their svn:mime-type property. This means, for example, that even if you had the niftiest Microsoft Word-aware differencing or merging tool in the Universe, it would never be invoked by Subversion so long as your versioned Word documents had a configured MIME type that denoted that they were not human-readable (such as application/msword). For more about MIME type settings, see the section called “File Content Type”

Subversion 1.5 introduces interactive resolution of conflicts (described in the section called “Resolve Conflicts (Merging Others' Changes)”), and one of the options provided to users is the ability launch a third-party merge tool. If this action is taken, Subversion will consult the merge-tool-cmd runtime configuration option to find the name of an external merge tool and, upon finding one, launch that tool with the appropriate input files. This differs from the configurable 3-way differencing tool in a couple of ways. First, the differencing tool is always used to handle 3-way differences, whereas the merge tool is only employed when 3-way difference application has detected a conflict. Secondly, the interface is much cleaner—your configured merge tool need only accept on its command line four path specifications: the base file, the “theirs” file (which contains upstream changes), the “mine” file (which contains local modifications), and the path of the file where the final resolved contents should be stored.