This text is a work in progress—highly subject to change—and may not accurately describe any released version of the Apache™ Subversion® software. Bookmarking or otherwise referring others to this page is probably not such a smart idea. Please visit http://www.svnbook.com/ for stable versions of this book.
Subversion 仓库就像一台时间机器, 它记录了用户提交的每一次修改, 允许用户查看文件和目录以前的版本, 以及它们的元数据. 只要一个命令, 用户就可以检出仓库在以前任意一个时间点或版本号的版本 (或者回滚工作 副本的版本号). 不过, 有时候用户可能只是想看一下过去的历史, 而不是想真正地回到过去.
下面几个命令提供了检索历史数据的功能:
从行的级别上查看修改的内容
和版本号绑定的日志消息, 及其日期, 作者, 以及受影响的文件 路径.
根据给定的版本号, 输出文件在该版本下的内容.
根据给定的版本号, 查看该版本下的文件的每一行的最后一 次修改信息.
根据给定的版本号, 列出仓库在该版本下的文件与目录清单.
我们已经介绍过 svn 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 $
最后, 即使本地机器上没有工作副本, svn diff 也可以比较仓库的版本号, 方法是在命令行中指定 URL:
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt … $
为了查看某个文件或目录的历史修改信息, 使用命令 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 ------------------------------------------------------------------------
注意, svn log 默认按照时间逆序来打印消息,
如果用户只想查看某段范围内的日志, 或者是单个版本号的日志, 又或者是想
改变打印顺序, 就带上选项 --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 …
上面的命令只会显示和 foo.c
相关的版本号的
日志.
如果用户想在日志消息中看到更多的细节, 就带上选项
--verbose
(-v
). 因为 Subversion
允许用户移动和复制文件或目录, 所以如果能在日志中看到文件路径的变化
就方便多了. 带上选项 --verbose
(-r
)
后, 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
) 一起使用,
那么 svn log 只会打印被修改的文件路径.
从 Subversion 1.7 开始, 用户还可以让 svn log
产生标准差异格式的输出, 就像 svn diff. 如果给
svn log 加上选项 --diff
,
用户就可以在行的级别上看到本次修订的具体修改内容, 于是, 用户可以同
时从高层的语义修改和底层的基于行的变化来查看文件的修改历史.
从 Subversion 1.8 开始, svn log 支持选项
--search
和 --search-and
. 这两个
选项允许用户指定搜索模式字符串, 从而过滤 svn log
的输出: 只有当版本号的作者, 日期, 日志消息或被修改的文件路径与搜索
模式匹配时, 才会输出该日志.
利用 svn cat 和 svn 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 会根据文件的当前内容输出每一行的属性:
$ 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 在输出中增加每一行的版本号的
提交日期 (这会显著增加输出内容的宽度, 所以我们不在这里展示添加
了选项 --verbose
后的运行效果).
和 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 就输出一条错误消息:
$ svn annotate images/logo.png Skipping binary file (use --force to treat as text): 'images/logo.png' $
就像错误消息中提示的那样, 用户可以通过增加选项
--force
来禁止 Subversion 去检查文件是否是人类
可读的. 如果用户强制要求 svn annotate 去读取
非人类可读的文件, 命令就会输出一堆混乱的信息:
$ svn annotate images/logo.png --force 6 harry \211PNG 6 harry ^Z 6 harry 7 harry \274\361\MI\300\365\353^X\300…
提示 | |
---|---|
根据执行命令时的心情, 用户可能不会使用标准形式 (svn annotate), 转而使用 svn blame 或 svn praise, 后面两种形式是 标准形式的别名, 它们是完全等价的. |
和许多获取信息的命令一样, svn annotate 也接受仓库的 URL 作为参数, 这样即使没有工作副本, 用户也可以照常 执行命令.
命令 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/
从左到右分别表示文件或目录最后一次被修改时的版本号, 作者, 文件大小 (仅针对文件), 日期以及文件或目录的名字.
警告 | |
---|---|
不带参数的 svn list 默认使用当前工作 目录对应的仓库 URL 作为参数, 而非本地的工作副本目录. 毕竟, 如果 用户想要列出本地目录中的文件, 应该使用 Shell 命令 ls (或其他非 Unix 系统的等价命令). |
用户可以用带有选项 --revision
(-r
)
的 svn update 命令, 把整个工作副本回退到旧版本:
[7]
# Make the current directory look like it did in r1729. $ svn update -r 1729 Updating '.': … $
提示 | |
---|---|
许多 Subversion 新手会尝试利用上面的 svn update 例子来 “撤消” (undo) 已经提交的修改, 但是这不可能 实现, 因为如果被修改的文件的版本号比较旧, 那就无法成功提交. 关于如何 “撤消” 提交请参考 “恢复已删除的文件”一节 |
如果用户想以较老的快照为基础创建一个新的工作副本, 只要稍微修改
一下 svn checkout 的命令行即可; 对于
svn update, 可以给它添加一个选项
--revision
(-r
). 由于
“限定版本号与实施版本号”一节 介绍的原因, 用户可能想
把目标版本号作为 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 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 … $