The interface between Subversion and external two- and three-way
differencing tools hearkens 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 that 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 would 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, and so on. Subversion continues to throw all those GNU utility options at your external diff tool regardless of whether that program can understand those options. And that’s where things get unintuitive for most users.
The key to using external two- and three-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 that Subversion expects—the format that the GNU tools would have used. The following sections cover the specifics of those expectations.
The decision of when to fire off a contextual two- or
three-way diff as part of a larger Subversion operation is made entirely
by Subversion and is affected by, among other things, whether 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 as 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 File Content Type.
Subversion 1.5 introduces interactive resolution of
conflicts—described in Resolve Conflicts (Merging Others’ Changes)—and one
of the options provided to users is the ability to 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, will launch that tool with the appropriate
input files. This differs from the configurable three-way differencing
tool in a couple of ways. First, the differencing tool is always used to
handle three-way differences, whereas the merge tool is employed only when
three-way difference application has detected a conflict. Second, the
interface is much cleaner—your configured merge tool need only accept as
command-line parameters 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.