本文档用于描述 Subversion 的 1.6.x 系列。如果您运行的是不同版本的 Subversion,强烈建议您访问 https://svnbook.subversion.org.cn/,并查阅适合您的 Subversion 版本的文档。

忽略未版本控制的项目

在任何给定的工作副本中,除了所有已版本控制的文件和目录之外,很可能还存在一些其他文件和目录,它们既未版本控制,也不打算版本控制。文本编辑器会在目录中留下备份文件。软件编译器会生成中间文件,甚至最终文件,这些文件通常不会被版本控制。用户也会将各种其他文件和目录随意放置,通常是在版本控制工作副本中。

期望 Subversion 工作副本在某种程度上不受这种混乱和杂乱的影响是荒谬的。事实上,Subversion 认为它的工作副本只是典型的目录,就像未版本控制的树一样,这是一个特性。但是,这些不需要版本控制的文件和目录可能会给 Subversion 用户带来一些烦恼。例如,因为 svn addsvn import 命令默认情况下会递归地执行,并且不知道您希望在给定树中版本控制哪些文件,因此很容易意外地将不应版本控制的内容添加到版本控制中。由于 svn status 默认情况下会报告工作副本中所有感兴趣的项目,包括未版本控制的文件和目录,因此在存在很多此类项目的情况下,其输出会变得非常嘈杂。

因此,Subversion 提供了两种方法来告诉它哪些文件您希望它忽略。其中一种方法涉及使用 Subversion 的运行时配置系统(请参阅 名为“运行时配置区域”的部分),因此适用于所有使用该运行时配置的 Subversion 操作,通常是针对特定计算机或特定计算机用户的操作。另一种方法利用 Subversion 的目录属性支持,它与版本控制树本身更紧密地绑定,因此影响所有拥有该树工作副本的用户。这两种机制都使用文件模式(包含字面字符和特殊通配符字符的字符串,用于与文件名匹配)来决定忽略哪些文件。

Subversion 运行时配置系统提供了一个选项 global-ignores,其值是空格分隔的文件模式集合。Subversion 客户端会将这些模式与作为版本控制添加候选的文件名以及 svn status 命令注意到的未版本控制的文件名进行匹配。如果任何文件的名称与其中一个模式匹配,Subversion 将基本上像该文件根本不存在一样进行操作。这对于您几乎从不希望版本控制的类型的文件非常有用,例如编辑器备份文件,例如 Emacs 的 *~.*~ 文件。

当在版本控制的目录中找到时,svn:ignore 属性应包含一个换行符分隔的文件模式列表,Subversion 应使用这些模式来确定同一目录中可忽略的对象。这些模式不会覆盖在 global-ignores 运行时配置选项中找到的模式,而是附加到该列表中。值得再次注意的是,与 global-ignores 选项不同,在 svn:ignore 属性中找到的模式仅适用于设置该属性的目录,而不适用于任何子目录。 svn:ignore 属性是一种很好的方法,可以告诉 Subversion 忽略可能存在于该目录每个用户工作副本中的文件,例如编译器输出,或者更适合本书的示例,将一些源 DocBook XML 文件转换为更易读的输出格式后生成的 HTML、PDF 或 PostScript 文件。

[Note] 注意

Subversion 对可忽略文件模式的支持仅限于将未版本控制的文件和目录添加到版本控制的一次性过程中。一旦对象在 Subversion 的控制之下,忽略模式机制就不再对其适用。换句话说,不要期望 Subversion 仅仅因为文件的名称与忽略模式匹配就避免提交对版本控制的文件的更改,Subversion 始终 会注意到所有版本控制的对象。

全局忽略模式列表往往更多地是个人品味问题,与用户特定工具链的联系比与特定工作副本需求的联系更紧密。因此,本节的其余部分将重点介绍 svn:ignore 属性及其用法。

假设您从 svn status 获得以下输出

$ svn status calc
 M      calc/button.c
?       calc/calculator
?       calc/data.c
?       calc/debug_log
?       calc/debug_log.1
?       calc/debug_log.2.gz
?       calc/debug_log.3.gz

在此示例中,您对 button.c 进行了一些属性修改,但在您的工作副本中,您还有一些未版本控制的文件:您从源代码编译的最新 calculator 程序,一个名为 data.c 的源文件,以及一组调试输出日志文件。现在,您知道您的构建系统始终会生成 calculator 程序。 [16] 您也知道您的测试套件始终会留下这些调试日志文件。这些事实适用于此项目的全部工作副本,而不仅仅是您自己的工作副本。您知道您不想每次运行 svn status 时都看到这些内容,而且您非常确定其他人也不想看到这些内容。因此,您可以使用 svn propedit svn:ignore calc 将一些忽略模式添加到 calc 目录中。

$ svn propget svn:ignore calc
calculator
debug_log*
$

添加此属性后,您将在 calc 目录上拥有一个本地属性修改。但请注意您的 svn status 输出中还有哪些不同之处

$ svn status
 M      calc
 M      calc/button.c
?       calc/data.c

现在,所有这些杂乱无章的东西都从输出中消失了!您的 calculator 编译程序和所有这些日志文件仍然存在于您的工作副本中,只是 Subversion 不会不断地提醒您它们存在且未版本控制。现在,所有不重要的噪音都从显示器中消失了,剩下的就是更有趣的内容,例如您可能忘记添加到版本控制中的源代码文件 data.c

当然,这并非您工作副本状态的唯一一种简明报告。如果您实际上想在状态报告中看到被忽略的文件,您可以将 --no-ignore 选项传递给 Subversion

$ svn status --no-ignore
 M      calc
 M      calc/button.c
I       calc/calculator
?       calc/data.c
I       calc/debug_log
I       calc/debug_log.1
I       calc/debug_log.2.gz
I       calc/debug_log.3.gz

如前所述,忽略文件模式列表也由 svn addsvn import 使用。这两种操作都涉及请求 Subversion 开始管理一组文件和目录。而不是强迫用户选择要开始版本控制的树中的哪些文件,Subversion 使用忽略模式(全局模式和每个目录模式)来确定哪些文件不应作为更大递归添加或导入操作的一部分被纳入版本控制系统。同样,您可以使用 --no-ignore 选项告诉 Subversion 忽略其忽略列表并对存在的所有文件和目录进行操作。

[Tip] 提示

即使设置了 svn:ignore,如果您在命令中使用 shell 通配符,您也可能会遇到问题。shell 通配符会在 Subversion 对其进行操作之前扩展为一个显式的目标列表,因此运行 svn SUBCOMMAND * 就如同运行 svn SUBCOMMAND file1 file2 file3 … 一样。对于 svn add 命令,这与传递 --no-ignore 选项的效果类似。因此,不要使用通配符,而要使用 svn add --force . 来进行未版本控制内容的大量添加调度。显式目标将确保当前目录不会因为已在版本控制之下而被忽略,而 --force 选项将导致 Subversion 遍历该目录,添加未版本控制的文件,同时仍然遵守 svn:ignore 属性和 global-ignores 运行时配置变量。如果您不想对要添加的内容进行完全递归遍历,请务必向 svn add 命令提供 --depth files 选项。



[16] 难道这不是构建系统的全部目的吗?