5.3 为初学者准备的CVS概述
如果您已经对CVS熟悉,那么可以跳过这一节。对于其他人来说,可以花一点时间来了解一下CVS的基本原理,并知道CVS中的一些专门术语。
CVS是一个开源项目。该开源项目起始于1986年,开始是由Dick Grune提供的一组简单UNIX SHELL命令表。在1986年,CVS得到了重大发展。当时,Brian Berliner设计并编码实现了CVS。从CVS诞生一直到现在,很多人都对CVS的发展作出了贡献。CVS可在很多平台(包括Windows、UNIX、Linux)上使用。有关CVS的更多信息,请访问http://www.cvshome.org。
与任何软件管理资源库一样,CVS对它所管理的那些文件的更改历史进行记录。小组成员可以获得CVS所管理的文件。尽管存在很多非常复杂的资源库,但是对于大小适中、代码所有权定义明确的小组来说,CVS使用起来可以非常高效。CVS没有提供故障或特征跟踪功能,也没有提供构建功能,也不提供其他资源库可能提供的对开发进程的支持。
Eclipse维护了一个CVS信息索引以及一个FAQ(frequently asked questions,常见问题解答)列表(参见本章最后的参考文献)。
5.3.1 CVS的一些重要设计原则
对于CVS来说,您的项目会被看作是一个模块。模块在CVS中显示为一个目录,它与工作空间中的项目非常相似。所以有时提到模块时会把它看作一个物理模块。CVS中还有逻辑模块或虚拟模块这一概念。逻辑模块是一个相关资源的集合。在一个被称作modules的特殊CVS文件中对逻辑模块中的相关资源进行了定义。Eclipse同时支持逻辑模块和物理模块。
CVS使用的是传统的命令界面。Eclipse使用该界面与CVS通信。如果需要从CVS资源库中取回某文件,就要使用一个被称为checkout的命令。如果需要将所做的改动传回到CVS中,就要使用commit命令。如果想用您最后一次从CVS中检出代码之后CVS中所发生的所有改动来刷新您的代码的本地副本,则使用update命令。幸运的是,Eclipse提供了一个CVS的GUI界面,这样,您不再需要直接使用这些CVS命令。在Eclipse的CVS用户界面中,您会看到这些命令项。如果感兴趣的话,您可以看一下Eclipse中的一个首选项设置。在该首选项设置中,对于和CVS通信的任何给定Eclipse操作,您都可以查看到它的实际执行的CVS命令(Team | CVS | Console页面)。如果您更喜欢使用CVS命令,那么可以在命令行环境中对工作空间项目直接执行这些命令(要了解这方面的更多信息,请参见Eclipse的联机帮助)。然后,您要确认已对自己的工作空间进行了刷新,或者请使用Eclipse的自动刷新功能。
我们知道,CVS资源库是被作为乐观锁模型来使用的。这就意味着,当您检出一个文件时,该文件在资源库没有被锁。访问CVS的其他人也可检出同一文件,并对该文件进行修改。在您将该文件重新保存到CVS资源库中时,您要对冲突进行管理。很多资源库使用的是悲观锁模型。在悲观锁模型中,当一个文件被检出时,该文件就被锁了起来。这就阻止其他人在该文件被检入之前更新该文件。Eclipse可与任何类型的资源库进行集成,而不管它使用的是哪种模型。CVS在冲突较少的环境中能高效工作。尽管冲突会不时发生,但正如我们所知的,Eclipse和CVS会帮助我们解决这些冲突。
5.3.2 修订版:任何东西都不会被丢失
由于CVS对文件更改进行了跟踪,所以每个更改都会被标识出来。CVS通过为它所管理的每个文件都使用一个修订版本号来实现这一点。文件每次被修改并被提交给CVS时,该文件就接受一个新的修订版本号。在文件第一次被提交时,其修订版本号是1.1。下一次,它获得修订版本号1.2,然后是1.3,以此类推。修订版本号可能非常长,并且有点复杂。在本章后面部分中,我们会对此有所涉及。
修订版本号可显示在Eclipse 的CVS Resource History视图、Navigator透视图以及其他显示工作空间资源的视图中。您可以总是访问一个文件的先前修订版。CVS还允许您用一个称作标签的文本标记来标识所感兴趣的资源。有些时候,这是一种访问老版本资源实例的较简单方法。在我们讨论版本设置时会对此进行详细讨论。
5.3.3 更新:跟上小组的进度
通过使用更新操作,被CVS管理的项目就可以接受您的同伴所做的任何更改。这样,工作空间中的资源是资源库中的最新资源。更新操作不会把您的文件覆盖掉。相反,该操作会自动对您的本地文件和CVS中该文件的最新实例进行合并(二进制文件除外)。如果在合并过程中出现冲突,那么合并操作就会结束,但是这时会用一个标识了该冲突(该冲突可引起不可预料的错误)的特定CVS标记文本来替换文本中的冲突行。Eclipse为最小化这些不可预料的冲突提供了备选同步机制。如果同事之间的代码所有权被良好定义,那么冲突会很少,而此时的CVS更新操作则更像是一个添加操作。
Eclipse对CVS更新操作提供了支持。这是通过Eclipse的Team | Update…操作和Synchronize with Repository…操作实现的。任何工作空间资源都可以使用这两个操作。我们稍后会对这两个操作进行详细介绍。在Workbench User Guide中有一个名为Working in the Team Environment with CVS的主题,在该主题的Updating部分对如何处理冲突进行了描述。
5.3.4 提交:共享您的资源
与更新操作相对的是提交操作。更新操作是从资源库中往外“拉”信息,而提交操作是往资源库中“推”信息。在执行CVS的提交操作时,您是在将您的更改推到资源库中,并使它们共享给小组中所有成员。这会导致您所修改的文件有了一个新的修订版本号。当然,提交是一个要认真对待的操作,您在提交之前要确信自己所做的修改。如果因为某人在您前面提交了文件的修改而导致在您提交该文件的修改时产生冲突,那么您的提交操作将失败。在提交您的更改之前,您应该总是先与CVS进行同步以降低冲突的可能性。
5.3.5 版本设置:捕获资源的当前状态
CVS提供了允许您用文本标记来标识文件修订版的机制。该文本标记变成了一个可被用来引用特定版本的符号名。通常,只对单个文件进行标识不是非常有用。一般情况下,您会对一组特定文件进行标识。这组文件表示已完成的部分工作。在CVS的术语中,在到达一个重要的里程碑时,您会对模块(相当于Eclipse中的项目)进行标记。模块中所有文件的最新修订版都用同一符号名来标记。您可将这组被标记的文件看作是一个版本。项目中被标以相同标记的文件可拥有不同的修订版本号,理解这一点很重要。对于任何特定的外部更改(例如一个错误或功能增强)来说,某些文件可能要作很多更改,某些文件可能更改不大,而另外一些文件可能根本就没发生更改。在设置项目版本时,您是对项目中所有文件的最新版本进行标记。某一具体版本所代表的那些项目资源不会发生改变;版本表示的是达到某些里程碑时的项目静态快照。在将某一版本的项目检出到工作空间的时候,您不能提交任何更改。但是,您可从一个版本创建一个分支并从那里开始进行修改。我们在下一专题中会对分支进行介绍。
CVS保存了一个被称为HEAD的标记名。在Eclipse用户界面中,您会看到HEAD标记。该标记代表了资源库的主开发分支(或干线)。
用日期进行标识也是可以的。这就允许您在特定日期(以及时间,可选)给资源库拍快照。您可使用时间标记来对CVS资源库进行比较、检出、合并或简单浏览。如同其他标记一样,时间标记只是该标记被创建时资源库内容的修订版本号的一个反射而已。
5.3.6 分支和合并:支持并行开发
分支代表了开发过程中的一个分叉。它使得您的项目更改独立于被称作HEAD的主开发流程。使用分支的原因有:
● 当进入到下一个版本开发时,您还正在对产品已完成版本中的错误进行处理。此时,您不想将修正后的代码与当前所开发的代码混淆。
● 您想创建一个维护分支,并要使该分支与当前正在进行并行开发的主功能版本相分离。所有的维护都将在该维护分支中进行,然后再合并到下一个主功能版本中。您做出了一个系统其他部分暂时还没有准备好的重大的开发更改,并想独立于开发主线来完成这次重大的开发更改,以避免对共享的基本代码造成问题。在更改完成后,您会将其合并到主功能版本中。
在CVS中是用分支标记来标识分支的。分支标记会对一组文件的最新版本进行划分。在Eclipse术语中,这就意味着工作空间中那些受CVS管理的项目资源会用分支名标识出来的。接着,您就可以独立于项目中可能发生的其他更改而自己执行更改操作,并将更改检入到CVS中。
在同一时候,文件或项目上可拥有多个分支。而一个分支又甚至可能产生其他分支。HEAD分支实质上是主分支。
在完成了分支中的代码后,您可能想将该分支与主分支合并。我们将简要涉及如何使用Eclipse来进行合并。合并的效果是将您在分支中所做的更改返回到该分支开始的开发主流程中去。例如,在已经纠正并测试了一个错误之后,您可能想将它合并到基准代码中。在执行合并操作时可能会涉及冲突的解决。这是因为,您所要合并的文件可能正在被其他人修改。Eclipse为您解决该冲突提供了帮助。Eclipse CVS支持为该冲突处理提供了一个备忘单。该备忘单可在Cheat Sheet Selection对话框中获得。如要打开Cheat Sheet Selection对话框,则在菜单栏上选择Help | Cheat Sheets…。
5.3.7 在分支和合并时对于修订版本号发生了什么
为了对分支中的变化进行跟踪,修订版本号会被扩展以合并分支。如果主分支HEAD中某文件的修订版本号是1.3,那么在创建新分支时,该文件的修订版本号就变成了1.3.2.1。修订版本号中的序数2是用来定义分支的,而最后那个序数1则指的是该分支中的修订版。当该文件的分支实例被提交到CVS中的时候,该文件的修订版本号就变成1.3.2.2,然后是1.3.2.3,依次类推。在已有分支被分叉时,CVS会添加两个或多个序数到版本数字的结尾以反映新分支和新分支的修订版。所以,修订版本号可以变得非常长。回想起我们在修订版1.3处进行了分支,这样就会创建修订版1.3.2.1。当我们完成了合并之后,最后的修订版本号将是1.4,它恰好是分支一开始停止的地方(否则,在分支开始和合并之间必有其他人进行过提交)。幸运的是,分支是以名称来标识的,所以我们就没有必要记住所有分支。
5.3.8 使用CVS管理二进制文件
尽管CVS为基于字符(ASCII)的文件提供了相当大的帮助,但它对二进制文件仅提供了基本支持。您可以在CVS中存储二进制文件并将它们作为修订版来管理(二进制文件需要以这种方式进行标识),但这就是CVS对二进制文件的所有支持了。在Team | File | Content首选项页面中按照文件类型(ASCII或二进制)列出了很多文件。
CVS会使用简单文件时间戳来检测二进制文件中的冲突。在CVS更新操作中,如果在二进制文件上检测到一个冲突,那么Eclipse会用资源库实例来替换您的本地实例。另外,本地文件实例的副本会被添加到您的项目中。该文件的文件名以字符“.#”(句号“.”后面跟着磅字符“#”)开头并以版本号结尾。您必须使用其他技术来处理这种冲突。






