5. 检验历史

Your Subversion repository is like a time machine. It keeps a record of every change ever committed and allows you to explore this history by examining previous versions of files and directories as well as the metadata that accompanies them. With a single Subversion command, you can check out the repository (or restore an existing working copy) exactly as it was at any date or revision number in the past. However, sometimes you just want to peer into the past instead of going into it.

有多个命令可以从版本库为你提供历史数据:

svn log

Shows you broad information: log messages with date and author information attached to revisions and which paths changed in each revision

svn diff

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

svn cat

Retrieves a file as it existed in a particular revision number and displays it on your screen

svn list

显示指定版本的目录中的文件

5.1. 产生历史修改列表

To find information about the history of a file or directory, use the svn log command. svn log will provide you with a record of who made changes to a file or directory, at what revision it changed, the time and date of that revision, and—if it was provided—the log message that accompanied the commit:

$ 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
------------------------------------------------------------------------

Note that the log messages are printed in reverse chronological order by default. If you wish to see a different range of revisions in a particular order or just a single revision, pass the --revision (-r) option:

$ svn log -r 5:19    # shows logs 5 through 19 in chronological order

$ svn log -r 19:5    # shows logs 5 through 19 in reverse order

$ svn log -r 8       # shows log for revision 8

You can also examine the log history of a single file or directory. For example:

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

These will display log messages only for those revisions in which the working file (or URL) changed.

If you want even more information about a file or directory, svn log also takes a --verbose (-v) option. Because Subversion allows you to move and copy files and directories, it is important to be able to track path changes in the filesystem. So, in verbose mode, svn log will include a list of changed paths in a revision in its output:

$ 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 also takes a --quiet (-q) option, which suppresses the body of the log message. When combined with --verbose (-v), it gives just the names of the changed files.

5.2. 检查历史修改详情

We've already seen svn diff before—it displays file differences in unified diff format; we used it to show the local modifications made to our working copy before committing to the repository.

事实上,svn diff种不同的用法:

  • 检查本地修改

  • 比较工作副本与版本库

  • 比较版本库中的版本

5.2.1. 检查本地修改

像我们看到的,不使用任何参数调用时,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
$

5.2.2. 比较工作副本和版本库

如果传递一个 --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
$

5.2.3. 比较版本库中的版本

如果通过 --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
$

A more convenient way of comparing one revision to the previous revision is to use the --change (-c) option:

$ 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
…
$

5.3. 浏览版本库

Using svn cat and svn list, you can view various revisions of files and directories without changing the working revision of your working copy. In fact, you don't even need a working copy to use either one.

5.3.1. svn cat

如果你只是希望检查一个过去的版本而不希望察看它们的区别,使用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
$

5.3.2. svn list

svn list可以在不下载文件到本地目录的情况下来察看目录中的文件:

$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/

如果你希望察看详细信息,你可以使用--verbose(-v) 参数:

$ svn list -v http://svn.collab.net/repos/svn
  20620 harry            1084 Jul 13  2006 README
  23339 harry                 Feb 04 01:40 branches/
  21282 sally                 Aug 27 09:41 developer-resources/
  23198 harry                 Jan 23 17:17 tags/
  23351 sally                 Feb 05 13:26 trunk/

这些列告诉你文件和目录最后修改的修订版本, 做出修改的用户, 如果是文件还会有文件的大小,最后是修改日期和项目的名字。

[警告] 警告

The svn list command with no arguments defaults to the repository URL of the current working directory, not the local working copy directory. After all, if you want a listing of your local directory, you could use just plain ls (or any reasonable non-Unixy equivalent).

5.4. 获得旧的版本库快照

In addition to all of the previous commands, you can use svn update and svn checkout with the --revision (-r) option to take an entire working copy back in time: [6]

$ svn checkout -r 1729 # Checks out a new working copy at r1729
…
$ svn update -r 1729 # Updates an existing working copy to r1729
…
[提示] 提示

Many Subversion newcomers attempt to use the preceding svn update example to undo committed changes, but this won't work as you can't commit changes that you obtain from backdating a working copy if the changed files have newer revisions. See 第 3.5 节 “找回删除的项目” for a description of how to undo a commit.

Lastly, if you're building a release and wish to bundle up your files from Subversion but don't want those pesky .svn directories in the way, you can use svn export to create a local copy of all or part of your repository sans .svn directories. As with svn update and svn checkout, you can also pass the --revision (-r) option to svn export:

$ svn export http://svn.example.com/svn/repos1 # Exports latest revision
…
$ svn export http://svn.example.com/svn/repos1 -r 1729
# Exports revision r1729
…


[6] 看到了吧?我们说过Subversion是一个时间机器。