本手册是为了描述 Subversion 1.2 而编写的。如果您正在运行更新版本的 Subversion,我们强烈建议您访问 https://svnbooks.subversion.org.cn/ 并查阅适合您 Subversion 版本的版本。

使用外部差异工具

--diff-cmd--diff3-cmd 选项以及类似的运行时配置参数(参见 名为“配置”的部分)的存在,可能导致人们误以为在 Subversion 中使用外部差异(或“diff”)和合并工具非常容易。虽然 Subversion 可以使用大多数流行的此类工具,但设置这些工具所需的努力往往并不容易。

Subversion 与外部 diff 和合并工具之间的接口可以追溯到 Subversion 唯一的上下文差异功能都是围绕 GNU diffutils 工具链的调用构建的时候,特别是 diffdiff3 实用程序。为了获得 Subversion 所需的行为,它使用多个选项和参数调用了这些实用程序,其中大多数参数都非常特定于这些实用程序。一段时间后,Subversion 开发了自己的内部差异库,作为一种故障转移机制,[40] 在 Subversion 命令行客户端中添加了 --diff-cmd--diff3-cmd 选项,以便用户可以更轻松地表明他们更喜欢使用 GNU diff 和 diff3 实用程序而不是新的内部差异库。如果使用了这些选项,Subversion 将简单地忽略内部差异库,并回退到运行这些外部程序,包括冗长的参数列表。这就是现状。

人们很快意识到,为指定 Subversion 应该使用系统特定位置的外部 GNU diff 和 diff3 实用程序而创建如此简单的配置机制也可以应用于其他 diff 和合并工具。毕竟,Subversion 并没有真正验证它被告知要运行的东西是否是 GNU diffutils 工具链的成员。但使用这些外部工具的唯一可配置方面是它们在系统中的位置,而不是选项集、参数顺序等。Subversion 继续将所有这些 GNU 实用程序选项传递给您的外部 diff 工具,无论该程序是否可以理解这些选项。这就是大多数用户感到困惑的地方。

使用外部 diff 和合并工具(当然除了 GNU diff 和 diff3 之外)与 Subversion 的关键在于使用包装脚本,将来自 Subversion 的输入转换为您的差异工具可以理解的东西,然后将您工具的输出转换回 Subversion 预期的格式,即 GNU 工具所使用的格式。以下部分将介绍这些期望的具体内容。

注意

在更大的 Subversion 操作中何时启动上下文 diff 或合并的决定完全由 Subversion 决定,并受多种因素的影响,包括正在操作的文件是否可读(由它们的 svn:mime-type 属性确定)。这意味着,例如,即使您拥有宇宙中最棒的 Microsoft Word 感知差异或合并工具,只要您版本控制的 Word 文档具有表示它们不可读的配置 MIME 类型(例如 application/msword),Subversion 就永远不会调用它。有关 MIME 类型设置的更多信息,请参见 名为“svn:mime-type”的部分

外部 diff

Subversion 使用适合 GNU diff 实用程序的参数调用外部 diff 程序,并且只期望外部程序返回成功错误代码。对于大多数替代 diff 程序,只有第六和第七个参数(表示 diff 的左右两边的文件的路径)是重要的。请注意,Subversion 为 Subversion 操作涉及的每个修改文件运行一次 diff 程序,因此如果您的程序以异步方式(或“后台”)运行,您可能会有多个程序实例同时运行。最后,Subversion 期望您的程序返回错误代码 0(如果您的程序检测到差异),或 1(如果它没有检测到差异),任何其他错误代码都被视为致命错误。[41]

示例 7.2,“diffwrap.sh”示例 7.3,“diffwrap.bat” 分别是 Bourne shell 和 Windows 批处理脚本语言中外部 diff 工具包装器的模板。

示例 7.2 diffwrap.sh

#!/bin/sh

# Configure your favorite diff program here.
DIFF="/usr/local/bin/my-diff-tool"

# Subversion provides the paths we need as the sixth and seventh 
# parameters.
LEFT=${6}
RIGHT=${7}

# Call the diff command (change the following line to make sense for
# your merge program).
$DIFF --left $LEFT --right $RIGHT

# Return an errorcode of 0 if no differences were detected, 1 if some were.
# Any other errorcode will be treated as fatal.

示例 7.3 diffwrap.bat

@ECHO OFF

REM Configure your favorite diff program here.
SET DIFF="C:\Program Files\Funky Stuff\My Diff Tool.exe"

REM Subversion provides the paths we need as the sixth and seventh 
REM parameters.
SET LEFT=%6
SET RIGHT=%7

REM Call the diff command (change the following line to make sense for
REM your merge program).
%DIFF% --left %LEFT% --right %RIGHT%

REM Return an errorcode of 0 if no differences were detected, 1 if some were.
REM Any other errorcode will be treated as fatal.

外部 diff3

Subversion 使用适合 GNU diff3 实用程序的参数调用外部合并程序,期望外部程序返回成功错误代码,并且合并操作完成后的完整文件内容将打印到标准输出流(以便 Subversion 可以将它们重定向到相应的版本控制文件)。对于大多数替代合并程序,只有第九、第十和第十一个参数(表示“我的”、“旧的”和“你的”输入的文件路径)是重要的。请注意,因为 Subversion 依赖于您的合并程序的输出,所以您的包装脚本必须在将该输出传递给 Subversion 之前不能退出。当它最终退出时,它应该返回错误代码 0(如果合并成功),或 1(如果输出中仍然存在未解决的冲突),任何其他错误代码都被视为致命错误。

示例 7.4,“diff3wrap.sh”示例 7.5,“diff3wrap.bat” 分别是 Bourne shell 和 Windows 批处理脚本语言中外部合并工具包装器的模板。

示例 7.4 diff3wrap.sh

#!/bin/sh

# Configure your favorite diff3/merge program here.
DIFF3="/usr/local/bin/my-merge-tool"

# Subversion provides the paths we need as the ninth, tenth, and eleventh 
# parameters.
MINE=${9}
OLDER=${10}
YOURS=${11}

# Call the merge command (change the following line to make sense for
# your merge program).
$DIFF3 --older $OLDER --mine $MINE --yours $YOURS

# After performing the merge, this script needs to print the contents
# of the merged file to stdout.  Do that in whatever way you see fit.
# Return an errorcode of 0 on successful merge, 1 if unresolved conflicts
# remain in the result.  Any other errorcode will be treated as fatal.

示例 7.5 diff3wrap.bat

@ECHO OFF

REM Configure your favorite diff3/merge program here.
SET DIFF3="C:\Program Files\Funky Stuff\My Merge Tool.exe"

REM Subversion provides the paths we need as the ninth, tenth, and eleventh 
REM parameters.  But we only have access to nine parameters at a time, so we
REM shift our nine-parameter window twice to let us get to what we need.
SHIFT
SHIFT
SET MINE=%7
SET OLDER=%8
SET YOURS=%9

REM Call the merge command (change the following line to make sense for
REM your merge program).
%DIFF3% --older %OLDER% --mine %MINE% --yours %YOURS%

REM After performing the merge, this script needs to print the contents
REM of the merged file to stdout.  Do that in whatever way you see fit.
REM Return an errorcode of 0 on successful merge, 1 if unresolved conflicts
REM remain in the result.  Any other errorcode will be treated as fatal.


[40] Subversion 开发人员很棒,但即使是最棒的人也会犯错。

[41] GNU diff 手册页是这样说的:“退出状态 0 表示没有发现差异,1 表示发现了一些差异,2 表示出现问题。

TortoiseSVN 官方中文版 1.14.7 发布