本文件编写时用于描述 Subversion 1.4。如果您运行的是更新版本的 Subversion,我们强烈建议您访问 https://svnbooks.subversion.org.cn/ 并查阅适合您 Subversion 版本的本书版本。

关键字替换

Subversion 能够将 关键字(版本化文件中的有用动态信息片段)替换到文件本身的内容中。关键字通常提供有关对文件进行的最后修改的信息。由于此信息在每次文件更改时都会发生变化,更重要的是,只会在文件更改 之后 发生变化,因此,除了版本控制系统之外,任何流程要保持数据完全最新都是很麻烦的。如果留给人工作者处理,这些信息不可避免地会过时。

例如,假设您有一个文档,您希望在其中显示最后修改它的日期。您可以让每个文档作者在提交更改之前,也调整描述上次更改时间的那部分文档。但迟早会有人忘记这样做。相反,只需让 Subversion 对 LastChangedDate 关键字执行关键字替换即可。您可以通过在文件中的所需位置放置一个 关键字锚点来控制关键字的插入位置。此锚点只是一个格式为 $KeywordName$ 的文本字符串。

所有关键字在作为文件中的锚点出现时都是区分大小写的:您必须使用正确的首字母大写才能使关键字扩展。您应该认为 svn:keywords 属性的值也是区分大小写的——某些关键字名称将被识别,无论大小写如何,但此行为已过时。

Subversion 定义了可用于替换的关键字列表。该列表包含以下五个关键字,其中一些有别名,您也可以使用它们

日期

此关键字描述文件在存储库中最后一次已知更改的时间,格式为 $Date: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $。它也可以指定为 LastChangedDate

修订版

此关键字描述此文件在存储库中最后一次已知更改的修订版,看起来像 $Revision: 144 $。它也可以指定为 LastChangedRevisionRev

作者

此关键字描述最后一次已知更改此文件在存储库中的用户,看起来像 $Author: harry $。它也可以指定为 LastChangedBy

HeadURL

此关键字描述存储库中文件的最新版本的完整 URL,看起来像 $HeadURL: http://svn.collab.net/repos/trunk/README $。它可以缩写为 URL

Id

此关键字是其他关键字的压缩组合。它的替换看起来像 $Id: calc.c 148 2006-07-28 21:30:43Z sally $,它被解释为文件 calc.c 最后一次更改是在 2006 年 7 月 28 日晚上由用户 sally 完成的,修订版为 148。

前面几个描述使用“最后一次已知”或类似的词语。请记住,关键字扩展是客户端操作,您的客户端只“知道”存储库中发生的更改,当您更新工作副本以包含这些更改时。如果您从未更新工作副本,即使这些版本化文件在存储库中定期更改,您的关键字也不会扩展到不同的值。

仅仅在您的文件中添加关键字锚点文本不会产生任何特殊效果。Subversion 永远不会尝试对您的文件内容执行文本替换,除非明确要求这样做。毕竟,您可能正在编写一篇关于如何使用关键字的文档 [14],并且您不希望 Subversion 替换您美丽的未替换关键字锚点示例!

要告诉 Subversion 是否要在特定文件上替换关键字,我们再次转向与属性相关的子命令。svn:keywords 属性在设置为版本化文件时,控制将在该文件上替换哪些关键字。该值是前面表格中找到的关键字名称或别名的空格分隔列表。

例如,假设您有一个名为 weather.txt 的版本化文件,它看起来像这样

Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

在该文件上没有设置 svn:keywords 属性的情况下,Subversion 不会执行任何特殊操作。现在,让我们启用 LastChangedDate 关键字的替换。

$ svn propset svn:keywords "Date Author" weather.txt
property 'svn:keywords' set on 'weather.txt'
$

现在,您已经对 weather.txt 文件进行了本地属性修改。您将不会看到文件内容的任何更改(除非您在设置属性之前自己进行了一些更改)。请注意,该文件包含 Rev 关键字的关键字锚点,但我们没有将该关键字包含在设置的属性值中。Subversion 将愉快地忽略对替换文件中不存在的关键字的请求,并且不会替换 svn:keywords 属性值中不存在的关键字。

在您提交此属性更改后,Subversion 将使用新的替换文本更新您的工作文件。您将不会看到您的关键字锚点 $LastChangedDate$,而是看到它的替换结果。该结果还包含关键字的名称,并且仍然由美元符号 ($) 字符包围。正如我们预测的那样,Rev 关键字没有被替换,因为我们没有要求它被替换。

另请注意,我们将 svn:keywords 属性设置为“Date Author”,但使用的关键字锚点是别名 $LastChangedDate$,并且仍然正确扩展。

Here is the latest report from the front lines.
$LastChangedDate: 2006-07-22 21:42:37 -0700 (Sat, 22 Jul 2006) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.

如果其他人现在提交了对 weather.txt 的更改,您的该文件副本将继续显示与之前相同的替换关键字值,直到您更新工作副本。届时,您 weather.txt 文件中的关键字将使用反映对该文件进行的最新已知提交的信息重新替换。

Subversion 1.2 引入了关键字语法的新的变体,它带来了额外的、有用的——尽管可能是非典型的——功能。您现在可以告诉 Subversion 维护替换的关键字的固定长度(以字节数衡量)。通过在关键字名称后面使用双冒号 (::),后跟一定数量的空格,您可以定义该固定宽度。当 Subversion 去替换关键字及其值时,它实际上只替换这些空格,使关键字字段的总宽度保持不变。如果替换的值小于定义的字段宽度,则在替换字段的末尾将有额外的填充字符(空格);如果它太长,则它将在最终美元符号终止符之前的特殊哈希 (#) 字符处被截断。

例如,假设您有一个文档,其中有一部分表格数据反映了该文档的 Subversion 关键字。使用原始的 Subversion 关键字替换语法,您的文件可能看起来像这样

$Rev$:     Revision of last commit
$Author$:  Author of last commit
$Date$:    Date of last commit

现在,这在事情刚开始的时候看起来很不错。但是,当您提交该文件时(当然,启用了关键字替换),您会看到

$Rev: 12 $:     Revision of last commit
$Author: harry $:  Author of last commit
$Date: 2006-03-15 02:33:03 -0500 (Wed, 15 Mar 2006) $:    Date of last commit

结果并不那么漂亮。您可能会想在替换后调整该文件,以便它再次看起来像表格。但这只有在关键字值具有相同宽度的情况下才成立。如果最后提交的修订版进入一个新的位值(比如,从 99 变为 100),或者如果另一个用户名更长的用户提交了该文件,东西就会再次变得歪歪扭扭。但是,如果您使用的是 Subversion 1.2 或更高版本,您可以使用新的固定长度关键字语法,定义一些看起来正常的字段宽度,现在您的文件可能看起来像这样

$Rev::               $:  Revision of last commit
$Author::            $:  Author of last commit
$Date::              $:  Date of last commit

您提交此更改到您的文件。这一次,Subversion 注意到新的固定长度关键字语法,并根据您在双冒号和尾随美元符号之间放置的填充来维护字段的宽度。替换后,字段的宽度完全保持不变——RevAuthor 的短值用空格填充,而长的 Date 字段则被一个哈希字符截断

$Rev:: 13            $:  Revision of last commit
$Author:: harry      $:  Author of last commit
$Date:: 2006-03-15 0#$:  Date of last commit

当对自身使用固定长度字段来存储数据的复杂文件格式执行替换时,或者当给定数据字段的存储大小难以从格式的本机应用程序外部修改时(例如,对于 Microsoft Office 文档),使用固定长度关键字特别方便。

警告

请注意,由于关键字字段的宽度是以字节为单位测量的,因此存在破坏多字节值的可能性。例如,包含一些多字节 UTF-8 字符的用户名可能会在构成其中一个字符的字节字符串的中间被截断。结果将在字节级别上仅被截断,但在作为 UTF-8 文本查看时,可能会显示为字符串,其最后一个字符不正确或乱码。可以想象,某些应用程序在被要求加载该文件时,会注意到损坏的 UTF-8 文本,并认为整个文件已损坏,从而拒绝完全操作该文件。因此,在将关键字限制为固定大小时,请选择一个允许这种字节级扩展的大小。



[14] … 或者甚至是一本书的部分 …

TortoiseSVN 官方中文版 1.14.7 发布