工作副本
你已经阅读过了关于工作副本的内容,现在我们要讲一讲客户端怎样建立和使用它。
一个 Subversion 工作副本是你本地机器一个普通的目录,保存着一些文件,你可以任意的编辑文件,而且如果是源代码文件,你可以像平常一样编译,你的工作副本是你的私有工作区,在你明确的做了特定操作之前,Subversion 不会把你的修改与其他人的合并,也不会把你的修改展示给别人。
After you've made some changes to the files in your working copy and verified that they work properly, Subversion provides you with commands to publish
一个工作副本也包括一些由 Subversion 创建并维护的额外文件,用来协助执行这些命令。通常情况下,你的工作副本每一个文件夹有一个以 .svn
为名的文件夹,也被叫做工作副本管理目录,这个目录里的文件能够帮助 Subversion 识别哪一个文件做过修改,哪一个文件相对于别人的工作已经过期了。
一个典型的 Subversion 的版本库经常包含许多项目的文件(或者说源代码),通常每一个项目都是版本库的子目录,在这种安排下,一个用户的工作副本往往对应版本库的的一个子目录。
举一个例子,你的版本库包含两个软件项目。
图 2.6. 版本库的文件系统
换句话说,版本库的根目录包含两个子目录: paint
和 calc
。
To get a working copy, you must check out some subtree of the repository. (The term check out
假定你修改了 button.c
,因为 .svn
目录记录着文件的修改日期和原始内容,Subversion 可以告诉你已经修改了文件,然而,在你明确告诉它之前,Subversion 不会将你的改变公开。将改变公开的操作被叫做提交(或者是检入),它提交修改到版本库中。
发布你的修改给别人,可以使用 Subversion 的提交命令。
这时你对 button.c
的修改已经提交到了版本库,如果其他人取出了 /calc
的一个工作副本,他们会看到这个文件最新的版本。
设你有个合作者,Sally,她和你同时取出了 /calc
的一个工作副本,你提交了你对 button.c
的修改,Sally 的工作副本并没有改变,Subversion 只在用户要求的时候才改变工作副本。
要使项目最新,Sally 可以要求 Subversion 更新她的工作副本,通过使用更新命令,可以将你和所有其他人在她上次更新之后的修改合并到她的工作副本。
注意,Sally 不必指定要更新的文件,Subversion 利用 .svn
以及版本库的进一步信息决定哪些文件需要更新。
版本库的 URL
Subversion 可以通过多种方式访问-本地磁盘访问,或各种各样不同的网络协议,但一个版本库地址永远都是一个 URL,URL 方案反映了访问方法。
表 2.1. 版本库访问 URL
方案 | 访问方法 |
| 直接版本库访问(本地磁盘或者网络磁盘)。 |
| 通过 WebDAV 协议访问支持 Subversion 的 Apache 服务器。 |
| 与 |
| 通过未认证的 TCP/IP 自定义协议访问 |
| 通过认证并加密的 TCP/IP 自定义协议访问 |
For the most part, Subversion's URLs use the standard syntax, allowing for server names and port numbers to be specified as part of the URL. The file://
access method is normally used for local access, although it can be used with UNC paths to a networked host. The URL therefore takes the form file://hostname/path/to/repos
. For the local machine, the hostname
portion of the URL is required to be either absent or localhost
. For this reason, local paths normally appear with three slashes, file:///path/to/repos
.
Also, users of the file://
scheme on Windows platforms will need to use an unofficially “standard” syntax for accessing repositories that are on the same machine, but on a different drive than the client's current working drive. Either of the two following URL path syntaxes will work where X
is the drive on which the repository resides:
file:///X:/path/to/repos... file:///X|/path/to/repos ...
注意 URL 使用普通的斜杠,而不是 Windows 本地(非 URL)形式的路径。
你可以安全的访问网络共享的 FSFS 版本库,但是你不能以这种方式访问 BDB 版本库。
警告
不要创建和访问网络共享上的 Berkeley DB 版本库,它不能存在于一个远程的文件系统,即使是映射到盘符的共享。如果你希望在网络共享使用 Berkeley DB,结果难以预料-你可能会立刻看到奇怪的错误,也有可能几个月之后才发现数据库已经损坏了。
修订版本
svn commit
在版本库中,每次提交被当作一次原子事务操作: 要么所有的改变发生,要么都不发生,Subversion 努力保持原子性以应对程序错误、系统错误、网络问题和其他用户行为。
每当版本库接受了一个提交,文件系统进入了一个新的状态,叫做版本,每个版本被赋予一个独一无二的自然数,一个比一个大,初始修订号是 0,只创建了一个空目录,没有任何内容。
可以形象的把版本库看作一系列树,想象有一组版本号,从 0 开始,从左到右,每一个修订号有一个目录树挂在它下面,每一个树好像是一次提交后的版本库“快照”。
图 2.7. 版本库
全局版本号
不像其它版本控制系统,Subversion 的版本号是针对整个目录树的,而不是单个文件。每一个版本号代表了一次提交后版本库整个目录树的特定状态,另一种理解是版本 N 代表版本库已经经过了 N 次提交。当 Subversion 用户讨论“foo.c
的版本 5”时,他们的实际意思是“在版本 5 时的foo.c
”。需要注意的是,一个文件的版本 N 和 M 并不表示它必定不同。
需要特别注意的是,工作副本并不一定对应版本库中的单一版本,他们可能包含多个版本的文件。举个例子,你从版本库检出一个工作副本,最新的版本是 4:
calc/Makefile:4 integer.c:4 button.c:4
此刻,工作目录与版本库的版本 4 完全对应,然而,你修改了 button.c
并且提交之后,假设没有别的提交出现,你的提交会在版本库建立版本 5,你的工作副本会是这个样子的:
calc/Makefile:4 integer.c:4 button.c:5
假设此刻,Sally 提交了对 integer.c
的修改,建立修订版本 6,如果你使用 svn update
calc/Makefile:6 integer.c:6 button.c:6
Sally 对 integer.c
的改变会出现在你的工作副本,你对 button.c
的改变还在,在这个例子里,Makefile
在 4、5、6 版本都是一样的,但是 Subversion 会把 Makefile
的版本设为 6 来表明它是最新的,所以你在工作副本顶级目录作一次干净的更新,会使所有内容对应版本库的同一修订版本。
工作副本怎样跟踪版本库
对于工作副本的每一个文件,Subversion 在管理目录 .svn/
记录两项关键的信息:
- 工作文件的基准版本(叫做文件的工作版本)和
- 一个本地副本最后更新的时间戳。
给定这些信息,通过与版本库通讯,Subversion 可以告诉我们工作文件是处与如下四种状态的那一种:
未修改且是当前的
文件在工作目录里没有修改,在工作版本之后没有修改提交到版本库。svn commit 操作不做任何事情,svn update
本地已修改且是当前的
工作副本已经修改,从基准版本之后没有修改提交到版本库。本地修改没有提交,因此 commit 会成功的提交,update
本地未修改且过时
这个文件在工作副本没有修改,但在版本库中已经修改了。这个文件应当更新到最新公共版本。commit 不做任何事情,update
本地已修改且过时
The file has been changed both in the working directory, and in the repository. A commit of the file will fail with an out-of-date error. The file should be updated first; an update