本文档旨在描述 Apache™ Subversion® 的 1.7.x 系列。如果您运行的是其他版本的 Subversion,强烈建议您访问 https://svnbook.subversion.org.cn/,并查阅适合您 Subversion 版本的文档。

查看历史记录

您的 Subversion 仓库就像一台时光机。它记录了所有提交的更改,并允许您通过查看文件的先前版本和目录以及伴随它们的元数据来探索此历史记录。使用单个 Subversion 命令,您可以检出仓库(或恢复现有工作副本),使其与过去任何日期或修订号时的状态完全相同。但是,有时您只想 窥视过去,而不是 进入过去。

几个命令可以为您提供仓库中的历史数据

svn diff

显示特定更改的行级详细信息

svn log

向您显示广泛的信息:日志消息,其中包含与修订版关联的日期和作者信息,以及每个修订版中更改的路径

svn cat

检索特定修订号中存在的文件,并在屏幕上显示它

svn annotate

检索特定修订号中存在的可读文件,以表格形式显示其内容,并将最后更改信息归因于文件的每一行。

svn list

显示任何给定修订版的目录中的文件

查看历史更改的详细信息

我们之前已经看到过 svn diff——它以统一的 diff 格式显示文件差异;我们使用它来显示在提交到仓库之前对工作副本进行的本地修改。

事实上,事实证明 svn diff三种不同的用途

  • 查看本地更改

  • 将您的工作副本与仓库进行比较

  • 比较仓库修订版

检查本地更改

正如我们所见,在没有选项的情况下调用 svn diff 将比较您的工作文件与 .svn 区域中缓存的 原始 副本

$ svn diff
Index: rules.txt
===================================================================
--- rules.txt	(revision 3)
+++ rules.txt	(working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$

比较工作副本与仓库

如果传递单个 --revision (-r) 编号,您的工作副本将与仓库中指定的修订版本进行比较

$ svn diff -r 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt	(revision 3)
+++ rules.txt	(working copy)
@@ -1,4 +1,5 @@
 Be kind to others
 Freedom = Responsibility
 Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$

比较仓库修订版本

如果通过 --revision (-r) 传递两个用冒号分隔的修订版本编号,则直接比较这两个修订版本

$ svn diff -r 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt	(revision 2)
+++ rules.txt	(revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open
$

比较一个修订版本与前一个修订版本的一种更方便的方法是使用 --change (-c) 选项

$ svn diff -c 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt	(revision 2)
+++ rules.txt	(revision 3)
@@ -1,4 +1,4 @@
 Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
 Everything in moderation
 Chew with your mouth open
$

最后,即使您在本地机器上没有工作副本,也可以通过在命令行中包含相应的 URL 来比较仓库修订版本

$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt
…
$

生成历史更改列表

要查找有关文件或目录历史记录的信息,请使用 svn log 命令。 svn log 将为您提供谁对文件或目录进行了更改、更改的修订版本、该修订版本的时间和日期以及(如果提供)提交时附带的日志消息的记录

$ svn log
------------------------------------------------------------------------
r3 | sally | 2008-05-15 23:09:28 -0500 (Thu, 15 May 2008) | 1 line

Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | 2008-05-14 18:43:15 -0500 (Wed, 14 May 2008) | 1 line

Added main() methods.
------------------------------------------------------------------------
r1 | sally | 2008-05-10 19:50:31 -0500 (Sat, 10 May 2008) | 1 line

Initial import
------------------------------------------------------------------------

请注意,默认情况下,日志消息按 反向时间顺序 打印。如果您希望以特定顺序查看不同范围的修订版本或仅查看单个修订版本,请传递 --revision (-r) 选项

表 2.1. 常用日志请求

命令 描述
svn log -r 5:19 按时间顺序显示修订版本 5 到 19 的日志
svn log -r 19:5 按反向时间顺序显示修订版本 5 到 19 的日志
svn log -r 8 仅显示修订版本 8 的日志

您还可以检查单个文件或目录的日志历史记录。例如

$ svn log foo.c
…
$ svn log http://foo.com/svn/trunk/code/foo.c
…

这些日志消息将显示在工作文件(或 URL)发生更改的修订版中。

如果您想获取有关文件或目录的更多信息,svn log 还接受 --verbose (-v) 选项。由于 Subversion 允许您移动和复制文件和目录,因此能够跟踪文件系统中的路径更改非常重要。因此,在详细模式下,svn log 将在其输出中包含修订版中更改的路径列表。

$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2008-05-21 13:19:25 -0500 (Wed, 21 May 2008) | 1 line
Changed paths:
   M /trunk/code/foo.c
   M /trunk/code/bar.h
   A /trunk/code/doc/README

Frozzled the sub-space winch.

------------------------------------------------------------------------

svn log 还接受 --quiet (-q) 选项,该选项会抑制日志消息的主体。当与 --verbose (-v) 结合使用时,它只给出更改文件的名称。

从 Subversion 1.7 开始,Subversion 命令行用户还可以利用 svn log 的特殊输出模式,该模式集成了类似于我们之前介绍的 svn diff 命令生成的差异报告。当您使用 --diff 选项调用 svn log 时,Subversion 将在日志报告中的每个修订版日志块后面追加一个 diff 样式的差异报告。这是一种非常方便的方式,可以同时查看修订版的高级语义更改和基于行的修改!

浏览仓库

使用 svn catsvn list,您可以查看文件的各种修订版本和目录,而无需更改工作副本的工作修订版本。事实上,您甚至不需要工作副本就可以使用它们中的任何一个。

显示文件内容

如果您想检查文件的早期版本,而不是两个文件之间的差异,您可以使用 svn cat

$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$

您也可以将输出直接重定向到文件

$ svn cat -r 2 rules.txt > rules.txt.v2
$

显示逐行更改归属

与我们在上一节中讨论的 svn cat 命令非常相似的是 svn annotate 命令。此命令也显示版本化文件的内容,但它使用表格格式。每行输出不仅显示文件内容的一行,还显示用户名、修订版本号和(可选)最后修改该行的修订版本的日期戳。

当与工作副本文件目标一起使用时,svn annotate 默认情况下将显示文件在工作副本中当前显示时的逐行归属。

$ svn annotate rules.txt
     1      harry Be kind to others
     3      sally Freedom = Responsibility
     1      harry Everything in moderation
     -          - Chew with your mouth closed
     -          - Listen when others are speaking

请注意,对于某些行,没有提供归属。在这种情况下,这是因为这些行已在工作副本版本的文件中修改。通过这种方式,svn annotate 成为您查看文件中已更改行的另一种方式。您可以使用 BASE 修订版本关键字(参见 名为“修订版本关键字”的部分)来查看驻留在工作副本中的文件的未修改形式。

$ svn annotate rules.txt@BASE
     1      harry Be kind to others
     3      sally Freedom = Responsibility
     1      harry Everything in moderation
     1      harry Chew with your mouth open

--verbose (-v) 选项会导致 svn annotate 在每行中还包含与该行报告的修订版本号关联的日期戳。(这会为每行输出增加大量的宽度,因此我们将在此处跳过演示。)

svn cat 一样,您也可以要求 svn annotate 显示文件的先前版本。当您在找出最近修改特定感兴趣行的人员后,想要查看谁在之前修改了同一行时,这将是一个方便的技巧。

$ svn blame rules.txt -r 2
     1      harry Be kind to others
     1      harry Freedom = Chocolate Ice Cream
     1      harry Everything in moderation
     1      harry Chew with your mouth open

svn cat 命令不同,svn annotate 的功能与人类可读文件中的 的概念密切相关。因此,如果您尝试对 Subversion 确定为 不可 人类可读的文件(根据文件的 svn:mime-type 属性 - 参见 名为“文件内容类型”的部分 以获取详细信息)运行该命令,您将收到错误消息。

$ svn annotate images/logo.png
Skipping binary file: 'images/logo.png'
$

如错误消息所示,您可以使用 --force 选项禁用此检查,并继续进行注释,就好像文件的内容实际上是人类可读的和基于行的。当然,如果您强制 Subversion 尝试对非文本文件执行基于行的注释,您将得到您要求的:一屏幕的胡言乱语。

$ svn annotate images/logo.png --force
     6      harry \211PNG
     6      harry ^Z
     6      harry 
     7      harry \274\361\MI\300\365\353^X\300…
[Tip] 提示

根据您执行此命令时的情绪以及您执行此命令的原因,您可能会发现自己输入 svn blame …svn praise … 而不是使用规范的 svn annotate 命令形式。没关系——Subversion 开发人员已经预料到了这一点,所以这些特定的命令别名也能正常工作!

最后,与 Subversion 的许多信息命令一样,您也可以通过其存储库 URL 在 svn annotate 命令调用中引用文件,即使您没有准备好访问工作副本,也能访问这些信息。

列出版本化的目录

svn list 命令会显示存储库目录中的哪些文件,而不会实际将文件下载到您的本地机器。

$ svn list http://svn.example.com/repo/project
README
branches/
tags/
trunk/

如果您想要更详细的列表,请传递 --verbose (-v) 标志以获得如下输出

$ svn list -v http://svn.example.com/repo/project
  23351 sally                 Feb 05 13:26 ./
  20620 harry            1084 Jul 13  2006 README
  23339 harry                 Feb 04 01:40 branches/
  23198 harry                 Jan 23 17:17 tags/
  23351 sally                 Feb 05 13:26 trunk/

这些列告诉您文件或目录最后修改的修订版本、修改它的用户、如果是文件的大小、最后修改的日期以及项目的名称。

[Warning] 警告

没有参数的 svn list 命令默认使用当前工作目录的 存储库 URL而不是 本地工作副本目录。毕竟,如果您想要列出您的本地目录,您可以使用简单的 ls(或任何合理的非 Unix 等效项)。

获取旧的存储库快照

除了所有之前的命令之外,您还可以使用 --revision (-r) 选项与 svn update 一起使用,以将整个工作副本 倒回时间[8]

# Make the current directory look like it did in r1729.
$ svn update -r 1729
Updating '.':
…
$
[Tip] 提示

许多 Subversion 新手尝试使用前面的 svn update 示例来 撤消 已提交的更改,但这不会起作用,因为您无法提交从将工作副本倒回时间获得的更改,如果已更改的文件具有更新的修订版本。有关如何 撤消 提交的说明,请参阅 名为“恢复已删除的项目”的部分

如果您希望从旧快照创建一个全新的工作副本,可以通过修改典型的 svn checkout 命令来实现。与 svn update 一样,您可以提供 --revision (-r) 选项。但出于我们在 “Peg 和 Operative 修订版本”部分 中介绍的原因,您可能希望将目标修订版本指定为 Subversion 扩展 URL 语法的一部分。

# Checkout the trunk from r1729.
$ svn checkout http://svn.example.com/svn/repo/trunk@1729 trunk-1729
…
# Checkout the current trunk as it looked in r1729.
$ svn checkout http://svn.example.com/svn/repo/trunk -r 1729 trunk-1729
…
$

最后,如果您正在构建一个版本,并且希望捆绑您的版本化文件和目录,您可以使用 svn export 创建本地副本,其中不包含任何 .svn 管理目录。此子命令的基本语法与 svn checkout 相同。

# Export the trunk from the latest revision.
$ svn export http://svn.example.com/svn/repo/trunk trunk-export
…
# Export the trunk from r1729.
$ svn export http://svn.example.com/svn/repo/trunk@1729 trunk-1729
…
# Export the current trunk as it looked in r1729. 
$ svn export http://svn.example.com/svn/repo/trunk -r 1729 trunk-1729
…
$


[8] 看到了吧?我们告诉过你 Subversion 是一个时间机器。