本文字档正在编写中,内容可能会发生重大变化,可能无法准确描述 Apache™ Subversion® 软件的任何已发布版本。 将此页面设为书签或以其他方式将其推荐给他人可能不是一个好主意。 请访问 https://svnbook.subversion.org.cn/ 以获取本书的稳定版本。

变更列表

开发人员经常发现自己在任何给定时间都在处理对特定源代码片段的多个不同、独立的更改。 这并不一定是由于计划不周或某种形式的数字虐待狂造成的。 软件工程师在处理附近的一块源代码时,经常会从他的周边视野中发现错误。 或者,也许他正在进行一些大型更改,然后意识到他正在进行的解决方案最好作为几个较小的逻辑单元提交。 通常,这些逻辑单元并不很好地包含在某个模块中,与其他更改安全地隔离开来。 这些单元可能会重叠,修改同一模块中的不同文件,甚至修改同一文件中的不同行。

开发人员可以使用各种工作方法来保持这些逻辑更改的组织性。 有些人使用同一个存储库的单独工作副本,以保存正在进行的每个单独更改。 其他人可能会选择在存储库中创建短暂的功能分支,并使用一个不断切换以指向某个分支或其他分支的单一工作副本。 其他人则使用 diffpatch 工具来备份和还原与每个更改关联的补丁文件中未提交的更改。 每种方法都有其优缺点,在很大程度上,所做更改的细节会严重影响用于区分它们的方。法。

Subversion 提供了一个称为 变更列表 的功能,它为混合中添加了另一种方法。 变更列表基本上是应用于工作副本文件的任意标签(目前每个文件最多一个),其明确目的是将多个文件关联在一起。 使用过许多 Google 软件产品的人已经熟悉了这个概念。 例如,Gmail 没有提供传统的基于文件夹的电子邮件组织机制。 在 Gmail 中,您可以对电子邮件应用任意标签,并且如果多个电子邮件恰好共享特定标签,则可以说它们属于同一组。 那么,仅查看一组具有相似标签的电子邮件就成为一个简单的用户界面技巧。 许多其他 Web 2.0 网站拥有类似的机制——考虑由 YouTubeFlickr 等网站使用的 标签,应用于博客文章的 类别 等等。 人们今天理解数据的组织至关重要,但如何组织这些数据需要是一个灵活的概念。 老式的文件和文件夹范式对于某些应用程序来说过于僵化。

Subversion 的变更列表支持允许您通过将标签应用于要与该变更列表关联的文件来创建变更列表,删除这些标签,并将子命令操作的文件范围限制为仅包含特定标签的文件。 在本节中,我们将详细介绍如何执行这些操作。

创建和修改变更列表

您可以使用 svn changelist 命令创建、修改和删除变更列表。 更准确地说,您可以使用此命令设置或取消特定工作副本文件的变更列表关联。 变更列表在您首次使用该变更列表标记文件时被有效创建;当您从具有该标签的最后一个文件中删除该标签时,它将被删除。 让我们检查一个展示这些概念的使用场景。

Harry 正在修复计算器应用程序数学逻辑中的某些错误。 他的工作导致他更改了几个文件

$ svn status
M       integer.c
M       mathops.c
$

在测试他的错误修复时,Harry 注意到他的更改暴露了 button.c 中的用户界面逻辑中与之相关的错误。 Harry 决定也修复这个错误,并将它与他的数学修复作为一个单独的提交。 现在,在一个只有少数文件和少量逻辑更改的小工作副本中,Harry 可能可以将两个逻辑更改分组在脑海中组织,而不会遇到任何问题。 但是今天,为了帮助本书的作者,他将使用 Subversion 的变更列表功能。

Harry 首先创建一个变更列表,并将已经更改的两个文件与之关联。 他通过使用 svn changelist 命令为这些文件分配相同的任意变更列表名称来实现这一点

$ svn changelist math-fixes integer.c mathops.c
A [math-fixes] integer.c
A [math-fixes] mathops.c
$ svn status

--- Changelist 'math-fixes':
M       integer.c
M       mathops.c
$

如您所见,svn status 的输出反映了这个新的分组。

Harry 现在开始修复次要的 UI 问题。 由于他知道要更改哪个文件,因此他也将该路径分配给一个变更列表。 不幸的是,Harry不小心将第三个文件分配给了与前两个文件相同的变更列表

$ svn changelist math-fixes button.c
A [math-fixes] button.c
$ svn status

--- Changelist 'math-fixes':
        button.c
M       integer.c
M       mathops.c
$

幸运的是,Harry 发现了自己的错误。 在这一点上,他有两种选择。 他可以从 button.c 中删除变更列表关联,然后分配不同的变更列表名称

$ svn changelist --remove button.c
D [math-fixes] button.c
$ svn changelist ui-fix button.c
A [ui-fix] button.c
$

或者,他可以跳过删除,直接分配一个新的变更列表名称。 在这种情况下,Subversion 会首先警告 Harry button.c 正在从第一个变更列表中删除

$ svn changelist ui-fix button.c
D [math-fixes] button.c
A [ui-fix] button.c
$ svn status

--- Changelist 'ui-fix':
        button.c

--- Changelist 'math-fixes':
M       integer.c
M       mathops.c
$

Harry 现在在他的工作副本中拥有两个不同的变更列表,并且 svn status 将根据这些变更列表的确定结果对其输出进行分组。 请注意,即使 Harry 尚未修改 button.c,它仍然显示在 svn status 的输出中,因为它是有趣的,因为它具有变更列表分配。 无论是否包含本地修改,都可以随时将变更列表添加到文件或从文件中删除。

Harry 现在修复了 button.c 中的用户界面问题。

$ svn status

--- Changelist 'ui-fix':
M       button.c

--- Changelist 'math-fixes':
M       integer.c
M       mathops.c
$

变更列表作为操作过滤器

Harry 在上一节中看到的 svn status 输出中的视觉分组很好,但并不完全有用。 status 命令只是他可能希望对他工作副本执行的许多操作之一。 幸运的是,Subversion 的许多其他操作都了解如何通过使用 --changelist 选项在变更列表上进行操作。

当提供 --changelist 选项时,Subversion 命令将将其操作范围限制为仅分配了特定变更列表名称的文件。 如果 Harry 现在想查看他对 math-fixes 变更列表中的文件所做的实际更改,他 可以svn diff 命令行中显式列出构成该变更列表的仅这些文件。

$ svn diff integer.c mathops.c
Index: integer.c
===================================================================
--- integer.c	(revision 1157)
+++ integer.c	(working copy)
…
Index: mathops.c
===================================================================
--- mathops.c	(revision 1157)
+++ mathops.c	(working copy)
…
$

对于几个文件来说,这可以正常工作,但如果 Harry 的更改影响了 20 或 30 个文件怎么办? 那将是一长串令人讨厌的显式命名的文件。 不过,现在他正在使用变更列表,因此 Harry 可以从现在开始避免显式列出变更列表中的一组文件,而是仅提供变更列表名称

$ svn diff --changelist math-fixes
Index: integer.c
===================================================================
--- integer.c	(revision 1157)
+++ integer.c	(working copy)
…
Index: mathops.c
===================================================================
--- mathops.c	(revision 1157)
+++ mathops.c	(working copy)
…
$

当需要提交时,Harry 可以再次使用 --changelist 选项来将提交范围限制为某个变更列表中的文件。 他可能会通过执行以下操作来提交他的用户界面修复

$ svn commit -m "Fix a UI bug found while working on math logic." \
             --changelist ui-fix
Sending        button.c
Transmitting file data .
Committed revision 1158.
$

事实上,svn commit 命令提供了第二个与变更列表相关的选项:--keep-changelists。 通常,在提交文件后,会从文件删除变更列表分配。 但是,如果提供了 --keep-changelists,Subversion 会将变更列表分配保留在已提交(现在未修改)的文件上。 无论如何,提交分配给一个变更列表的文件都会保留其他变更列表不受干扰。

$ svn status

--- Changelist 'math-fixes':
M       integer.c
M       mathops.c
$
[Note] 注意

--changelist 选项仅充当 Subversion 命令目标的过滤器,不会将目标添加到操作中。 例如,在指定为 svn commit /path/to/dir 的提交操作中,目标是目录 /path/to/dir 及其子目录(直至无限深度)。 如果你然后向该命令添加变更列表说明符,则仅会将位于 /path/to/dir 中和之下,且已分配了该变更列表名称的文件视为提交的目标——提交不会包含其他地方(例如 /path/to/another-dir)的文件,无论它们是分配了哪个变更列表名称,即使它们是与操作目标相同的同一个工作副本的一部分。

即使 svn changelist 命令也接受 --changelist 选项。 这使您可以快速轻松地重命名或删除变更列表

$ svn changelist math-bugs --changelist math-fixes --depth infinity .
D [math-fixes] integer.c
A [math-bugs] integer.c
D [math-fixes] mathops.c
A [math-bugs] mathops.c
$ svn changelist --remove --changelist math-bugs --depth infinity .
D [math-bugs] integer.c
D [math-bugs] mathops.c
$

最后,您可以在单个命令行上指定 --changelist 选项的多个实例。 这样做会将您正在执行的操作限制在从任何指定变更集中找到的文件。

变更列表限制

Subversion 的变更列表功能是用于对工作副本文件进行分组的便捷工具,但它确实有一些限制。 变更列表是特定工作副本的工件,这意味着变更列表分配不能传播到存储库或以其他方式与其他用户共享。 变更列表只能分配给文件——Subversion 目前不支持将变更列表与目录一起使用。 最后,您可以在给定的工作副本文件中最多有一个变更列表分配。 这是博客文章类别和照片服务标签类比失效的地方——如果您发现自己需要将文件分配给多个变更列表,那么您就走运了。

TortoiseSVN 官方中文版 1.14.7 发布