(表格结束)
有一点非常重要,工作副本并不总是对应于仓库中一个单一的修订版,有时可能会包含几个其他修订版的文件。举个例子来说,假设你 check out 了一个仓库中的项目,修订版编号是 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 的修改会出现在你的本地工作副本中,而你的修改也仍然在 button.c 中。在这个例子里,文本文件 Makefile 在修订版4、5、6中是一样的,但是 Subversion 还是会把 Makefile 的本地工作副本标示为 revision 6 来表示它是最新的。所以,当你对你的工作副本做过一次更新之后,它将只对应仓库中"一个"修订版。
2.3.3 工作副本如何跟踪仓库
对于工作副本中的每一文件,Subversion 在 .svn/ 管理区中保存两条必需的信息:
?这个工作文件的修订版编号(也叫做文件的"工作版本");
?本地副本最后一次更新的时间戳。
基于这些信息,Subversion 通过和仓库来通讯,可以报告一个工作文件处于下面四种状态中的哪一种:
未改变的,并且是最新的
文件没有在工作副本中修改过,而且也没有人向仓库提交过修改。对此文件执行 svn commit 或是 svn update 是无效的。
在本地修改过,是最新的
文件在工作副本中修改过,没有其他人提交过目前修订版的修改。这时,可以执行 svn commit 来提交修改。而执行 svn update 是无效的。
未改变的,但是过时的
文件在工作副本中没有修改过,但是已经有其他人向仓库提交过修改。文件需要得到更新。执行 svn commit 是无效的。执行 svn update 可以得到文件的最新版本。
在本地修改过,并且是过时的
文件在工作副本中修改过,并且有其他工作者向仓库提交了此文件的新版本。执行 svn commit 将会得到一个 "out-of-date"的错误。应该先更新这个文件。执行 svn update 命令,Subversion 将试图将仓库中的修改合并到本地工作副本中。如果 Subversion 无法正确的自动合并修改,将不得不由用户亲自来解决冲突问题。
2.3.4 混合型修订版的局限性
一般的原则上,Subversion 努力使自己尽可能的灵活。一个典型的灵活性的体现就是允许工作副本中包含有混合的修订版编号的能力。
首先,这类型的灵活性是否可以称之为特性而不是一种负担我们并不是完全地清楚。在完成向仓库的提交之后,刚刚提交的文件和目录就拥有了最新的修订版编号,而其他文件没有。这显得有一些混乱。就像前面讲过的那样,工作副本随时可以使用 svn update 命令来更新到一个单一的修订版编号。为什么要"故意"地让修订版混合呢?
假设你的项目十分地复杂,你会发现有时强行将一部分工作副本恢复到以前的版本才行;在第三章你将学会怎样做。也许,你想要测试一个子目录中的早期版本的一个子模块,或者,你想检查一个文件的多个早期版本在最新的目录树中的工作情况。
然而,在工作副本中使用混合修订版也有其局限性。
第一,在你没有对文件或目录完全更新之前,你无法提交对他们的删除操作。如果仓库中存在一个新出现的文件或目录,你的删除请求将被拒绝。这是为了防止你破坏还没有见到的修改。
第二,在还没有完全更新之前,你将无法提交一个对目录元数据修改的操作。我们将在第六章学习如何为文件或目录附加"属性"。一个目录的工作副本定义了特定的一个条目和属性的集合。这样,如果提交一个对过期目录的属性的修改,将有可能破坏你还没有见到过的属性。
2.4 总结
我们在这一章中已经看到了许多基本的 Subversion 的概念:
? 我们介绍了中央仓库、工作副本的概念,以及仓库修订版序列。
? 我们看到了一些简单的例子。例如两个协作者如何使用"复制―修改―合并"模型,通过 Subversion 来发布自己的修改以及获取对方的修改。
