项目的版本控制对于团队开发是极端重要的,对于个人开发者也是项目复杂化时不可缺少的工具。
本文介绍如何在Eclipse中使用版本控制系统CVS。首先,我们将简要讨论一下团队代码开发的思想,然后简要讲述CVS系统的背景及Windows平台下CVS服务器的安装和设置。接下来,针对Eclipse,详细讲解了使用CVS进行团队开发时的开发流程以及在Eclipse中具体使用的重要操作方法。
现今的大多数应用程序是由多人组成的团队开发的。即使只涉及几个开发人员的小项目,也需要对源代码的更改进行严格控制。这就是源代码管理软件的任务。源代码版本控制软件必须支持两个核心功能:
- 提供一种方法,能够协调对源代码的更改,并能集成这些更改
- 团队所提交工作的历史记录
当团队成员完成新的工作时,通过将这些更改提交到资源库(repository)中来共享他们的工作。类似地,当他们希望获得最新可用的工作成果时,就可以根据资源库中的更改,更新自己的本地工作空间(Workbench)。这意味着资源库的内容会因团队成员提交新工作成果而经常发生更改团队成员都要能够根据资源库更新自己的工作空间,确信它们是最新的。
维护历史记录也很重要,那样就可以将当前工作与先前版本进行比较,如有必要,还可以回复到先前版本。协调团队的工作,以便只存在唯一的当前项目状态定义,以及包含团队已集成的工作,这些对于管理版本控制也是十分必要的。这种协调有可能是最难实现的目标。
最理想的模型是:团队的任何成员都可以对自己有权访问的任何资源进行更改。因为两个团队成员可以提交对同一资源的更改,所以有可能发生冲突,必须解决这种冲突。
这种模型假定冲突具有唯一性。但遗憾的是,没有任何源代码是孤立地存在的;通常它包含与其它资源隐式或显式的相关性。但源代码管理软件的工作就到此为止了,因为它并不能取代项目管理。项目管理者必须履行其职责:协调其它成员的工作以及负责进度、项目阶段和发布日期。此外,源代码管理也不能替代开发人员之间的交流。
内置版本支持
Eclipse本身内置了一定程度的版本支持,也就是所谓的Local History。在Eclipse中编辑的文件每次存盘都会留下记录,可以随时与历史记录比较,恢复到某一个时刻的状态。在资源视图(Resource Perspective)或者Java视图(Java Perspective)中的文件上点右键,选择Compare With,Local History,就会得到如下的画面,可以很清晰看到各个版本的区别。
Eclipse中的内置版本支持:Local History。
如果需要,则可以通过Replace With,Local History来恢复到任一个以前的版本。当然,这样版本的历史是有限制的,可以在Eclipse的Preference中设置。在Preference―>Workbench->Local History中,可以设置保持最多保持几天的文件,每一文件的版本数目,历史文件的大小限制。
但是,这样的版本系统只实现了最基本的版本功能,如果想把文件某一个状态标记为一个版本,加上注释(仅仅从Local History中的保存时间很难看出每一个版本的特点,也难以找到重要的关键版本),或者想把某个目录乃至整个项目版本化,Eclipse内置的Local History都是无能为力的。
好在Eclipse 平台提供了作为团队在软件项目中共享代码和工作的能力。
Eclipse 平台体系结构的重点在于工作空间。工作空间维护构建和测试软件项目所需的一切,它包含源代码和所需其它资源文件。工作空间是在开发人员的本地机器上进行维护的,但整个团队通过源代码管理系统进行协作,不同开发人员的代码在源代码管理系统中进行汇集。Eclipse平台只对一个源代码管理系统提供内置支持:并发版本控制系统(Concurrent Versions System,CVS)。
CVS是Concurrent Versions System(并发版本系统)的缩写,诞生于 1986 年,现在已经发展成了最流行的针对软件开发人员的源代码版本管理解决方案。CVS 是用于代码版本管理的开放源码的客户机/服务器解决方案,它可用于各种平台,包括 Linux 和 Windows NT/2000/XP。
通常,CVS 的主要功能是记录源文件的历史。当一组开发人员从事同一个项目时,CVS 将他们彼此隔离开来。每个开发人员都在他/她自己的目录中独立工作,然后使用 CVS 资源库(经常地)合并工作结果,共享其工作。
CVS采用客户机/服务器体系,代码以及各种版本存储在中心服务器内,每一个个体开发者开发时都首先从服务器上获得一份自己的拷贝,在此基础上进行开发,以避免直接影响服务器上的数据。开发者可以随时把自己的新代码提交给服务器;也可以通过更新获得代码的最新状态,保持与其他开发者的一致。
CVS对于网络是透明的,开发者可以使用客户端软件(几乎所有的平台上都有相应的客户端软件)在任何时候,任何地点通过网络来获取最新的代码。
对于Eclipse的开发者而言,Eclipse本身内置了CVS支持,Eclipse 拥有与 Eclipse 平台 IDE 紧密集成的内置 CVS 客户机,它是作为一个单独透视图(CVS Repository Exploring 透视图)而实现的,用于与 CVS 的交互。
HEAD与分支(Branch)
CVS 使用分支(branch)模型来支持彼此独立而又高度相互依赖的多个工作流程(course of work)。分支是开发团队用来共享正在进行中的工作的地方。任何时候,团队成员都可以使用一个分支的内容作为新工作的基础。
您在Eclipse工作空间中进行本地更改时,您的工作是基于某一个分支的。当您准备好让其他小组成员使用您对本地资源文件的更改时,需要将您的工作成果提交至分支。其他开发者稍后必须从分支更新。
每个 CVS 资源库都至少有一个分支,称为 HEAD。HEAD代表CVS里的主流分支。在特定情况下,资源库中可以存在多个分支。例如,一个分支可能用于正常的开发,而另一个分支可能用于实验新技术在当前项目的可用性的开发。
创建分支并将资源发布到该分支在尚未准备好将更改置于主开发流的情况下非常有用。对于创建现有版本的增量补丁程序也很有用。
模块(Module)
在CVS当中,您可以把本地工作空间中的项目放到一个资源库的HEAD分支中,CVS把它命名为模块。一个分支可以有许多模块。可以讲,您在本地工作空间中的项目是一个模块的本地工作拷贝。HEAD分支中具有所有的模块。模块可以具有子模块。模块可以被拷贝到其他分支中去。
修订版(Revision)
每个在本地修改的资源文件都属于某个分支,当您提交这个文件的修改后,CVS资源库都会对这个文件建立一个修订版,例如开始时某个文件是1.1版,您提交一次修改后,它将变成1.2版。
由于在一个项目当中,一些文件的提交要比另一些文件频繁,所以项目中不同文件的修订版的标号可能不同。
版本(Version)
版本是指某个分支中一个模块的当前状态的快照。当设置模块的版本(Tag as version)时,就意味着在资源库中建立该模块的不可修改副本。
一般我们会在每日创建模块的一个版本进行功能或集成测试,也会在项目完成前创建beta1、beta2等版本,会在项目完成后创建release版。
您应该在某一版本(Version)上创建分支,便于以后访问分支基点。
安装
CVS起源于Unix/Linux平台,但在Windows平台上也有CVS的一个实现――CVSNT,这里我们对CVSNT的安装做一个简单介绍,便于您实验CVS的操作。
首先到CVSNT的主页http://www.cvsnt.org下载最新版本。
CVSNT的安装有一些注意事项,请读者尽量按照下面所说的步骤来进行安装,描述主要针对Windows 2000。如果读者在安装过程中还有问题,可以参考本文附录的资源中关于CVSNT的安装技巧的文章或邮件列表。
1. CVSNT可以安装在Windows NT4 服务器或工作站SP6, Windows 2000服务器或专业版,Windows XP专业版上。
2. 以管理员账号登陆,首先修改环境变量。直接执行安装程序,很有可能在最后会出现无法创建路径变量的错误,为此我们首先修改环境变量,设定路径。假设我们要把CVSNT安装到D:\app\cvsnt目录下(与CVSNT相关的内容最好安装到NTFS分区上,也尽量不要使用含有空格的目录名或者文件名,虽然CVSNT已经尽量支持包含空格的目录名和文件名,但仍有可能出现问题),那么打开控制面板->系统属性->高级->环境变量->系统变量中的Path,添加上D:\app\cvsnt并保存设置。
3. 接下来可以执行安装程序,修改安装目录,一步步完成安装。
4. 从开始菜单的程序组中启动CVSNT配置程序Configure Server。这时应该看到服务器还没有运行(CVSNT作为系统服务运行),如果已经运行了,先把它停下来。
5. 选择第二个选项卡Repositories,首先勾上Repositories prefix(数据库路径前缀)的选项。CVSNT中只有一个数据库路径前缀,在这同一个前缀下,可以有多个数据库。相应的,所有的数据库都位于数据库路径前缀对应的目录之下。这里我们假设数据库都存储在E:\cvsnt\repo下,点击省略号按钮来选择E:\cvsnt\repo作为数据库路径前缀。
6. 点击下面的Add按钮添加资源库root,资源库root可以有多个。比如我们将/prototype作为我们的工作项目的存储根。注意添加时系统自动把已设定的E:\cvsnt\repo作为了路径前缀。
7. 选择第三个选项卡Advanced,勾上全部选项,包括Use local users instead of domain。设置临时目录,假设为E:\work\cvstemp。注意要保证临时目录的安全设置(右键点击目录属性,共享,权限)给所有帐号以完全控制权限,包括SYSTEM帐号。并且,绝对不能把临时目录设在诸如C:\WINNT\TEMP或者C:\Documents and Settings下的任何地方,因为这些地方对于用户的访问是有限制的。
8. 点击应用以保存设置,这一点相当重要。
9. 现在可以回到第一个选项卡,点击Start按钮,服务应该正常启动运行了。如果有问题,可以打开一个命令行窗口,输入path命令来检查路径是否已经设置正确,也许需要重新启动来使设置生效。
10. 打开一个命令行窗口,输入如下命令,用你的实际计算机ip地址、windows用户名和资源库root替代尖括号内相关的内容:
set cvsroot=:pserver: <windows用户名>@<计算机ip地址>:/<资源库root>
然后输入
cvs login
输入后将提示你输入windows用户密码。
这里的用户必须是服务器上的真实用户,不过可以给真实用户设定一个不同的使用名alias。使用命令:
cvs passwd -a -r <windows用户名> <CVS帐号别名>
必须注意,这些名字里最好不要使用任何空格。如果必须的话,可以用双引号括起来。
11. 到此为止,CVS服务器已经初步设置完成,可以使用了。缺省情况下,服务器将作为NT服务自动运行。读者既可以使用命令行的CVS命令,也可以使用各种CVS客户端来连接CVS服务器,执行CVS操作。不过,下面我们主要介绍在Eclipse中通过内置的CVS支持来使用CVS系统。
Eclipse中使用CVS系统
开发者可以提交(commit)自己的工作,并通过更新(update)与其他人的最新修改保持同步。提交是把自己的修改提交给数据库,更新则是得到其他人的修改。
因此,在Eclipse中使用CVS进行团队开发,理想的开发流程应该是这样的:
1. 开始工作前,要保证所有工作区的资源与最新的分枝状态一致。对于从头开始的新项目,首先要连接服务器,设定存储那些资源文件。对于在服务器数据库中已经有记录的项目,首先要通过更新来保证工作区的资源状态最新。
2. 进行本地工作,先在本地保存修改。
3. 与资源库同步。某一阶段工作完成后,要和资源库的数据同步。
1. 首先应该更新(Update),检查所有的Incoming改变,输入到本地,看是否会影响自己的工作,是否会造成冲突,破坏完整性等等。
2. 检查完更新后,可以确认自己的工作和最新的Branch内容是一致的,就可以提交(Commit)自己的修改了,标上适当的注释。
首先设置Eclipse来连接CVS服务器资源库,它将定义用于选定 CVS 服务器/资源库的连接参数。
切换到CVS Repository Exploring 透视图,使用菜单Window -> Open Perspective -> Other -> CVS Repository Exploring。
你也可以在Eclipse中设置一些CVS选项,可以通过Window -> Preferences window -> Team。具体含义我们将在后面的章节中论述。
在CVS Repository Exploring中右键选择new->repository location...,会出现下面屏幕。
在“主机Host”里可以输入localhost,因为我的CVS服务器就在本机上。
在“资源库repository”中输入你要连接的CVS的资源库名称,项目数据存放在这个路径下。
在“认证Authentication”中输入你在CVS服务器上的用户名和密码。
在“Connection type连接类型”中选择pserver,端口是缺省时不用改动。
注意:上述所有参数的更详细解释,查看CVSNT一节的具体描述,在实际项目中,各项参数的获得需要联系你的CVS管理人员。
接下来可以直接点击Finish完成设置。如果你选择了Validate Connection on Finish,那么,Eclipse会使用你提供的连接参数连接CVS资源库,如果失败,它会通知你。
开发人员可以通过将其现有的项目资源迁移到资源库中来共享它。
首先在Eclipse的资源视图(Resource Perspective)或者Java视图(Java Perspective)中要共享的项目上点右键,选择Team->Share Project,将出现提示窗口,选择是使用已知的CVS数据库位置还是新建数据库位置。我们将使用前面建立的连接,当然,我们可以定义新的连接,那将出现前面的设置资源库的位置步骤。
如果点击下一步,可以继续定义在CVS中是否使用与项目不同的名字作为模块名,缺省是使用相同的名字。模块与CVS资源库的目录对应,编写相同项目的团队共享CVS资源库中相同的目录。
注意在Eclipse右下角的Tasks和Console的位置新出现了一个Synchronize窗口。
同步视图上工具条的图标标明了同步(Synchronize)视图现在处于的模式。同步(Synchronize)视图有Incoming(入局)模式、Outgoing(出局)模式、Incoming/Outgoing(入局)/出局)模式和Conflicts(冲突)模式共四种模式。
Incoming模式时,同步(Synchronize)视图下列出所有需要更新(Update)的资源文件。
Incoming模式时,同步(Synchronize)视图下列出所有需要提交(Commit)的资源文件。
Incoming和Outgoing模式时,同步(Synchronize)视图下列出所有需要更新(Update)或提交(Commit)的资源文件。
Conflicts模式时,同步(Synchronize)视图下列出所有发生并发文件修改冲突的资源文件。可以通过合并(Merge)操作来消除对同一文件不同开发人员并行修改所带来的冲突。
注意,现在我们仅仅是在CVS资源库里增加了一个模块,项目的所有资源文件并没有被加到CVS资源库里。因为在一个项目中可能有相当一部分资源文件不适合存储到CVS资源库中记录版本信息,比如编辑器生成的临时文件,编译生成的.class文件,或者某些编译过程生成的二进制文件等等。因此,Eclipse并不自动把所有文件存储到数据库中,需要开发者手工指定把那些文件存储到CVS资源库里。
这时的同步视图上工具条的图标标明了同步(Synchronize)视图现在处于Outgoing模式。现在Synchronize窗口里列出了项目中尚未加入到CVS资源库的所有资源文件。
把文件存储到CVS资源库里中,需要二步。
第一步,我们需要通知CVS资源库那些文件将在其中记录其版本信息。
我们可以在资源视图(Resource Perspective)或者Java视图(Java Perspective)或者同步(Synchronize)视图中,同时选择多个文件或者目录,使用右键,选择Team->Add to version control,这时你会发现在同步(Synchronize)视图中这些文件或目录上的灰色箭头标记不见了。注意这些文件并没有在CVS资源库中记录其版本信息,只是通知CVS资源库。
第二步,我们需要执行提交(Commit)操作。
我们可以在资源视图(Resource Perspective)或者Java视图(Java Perspective)中,同时选择多个文件或者目录,使用右键,选择Team->Commit,或者在同步(Synchronize)视图中,同时选择多个文件或者目录,使用右键,选择Commit。
提交时都会提示你输入注释,作为提交的说明和提示。例如,第一次提交时我们可以输入“项目建立”。
如果你提交时选择的文件或目录有些没有经过第一步的Add to version control,Eclipse将要求你选择那些文件或目录将要被Add to version control。
在此之后,每当完成对文件或者项目的修改,需要把最新的状态存储到CVS资源库中去,就需要执行提交(Commit)操作。注意,每次提交时都会提示输入注释,这是很重要的,作为每一个状态的说明和提示。
我们需要告诉Eclipse那些资源文件被存储到CVS资源库中。
我们可以在资源视图(Resource Perspective)或者Java视图(Java Perspective)或者同步(Synchronize)视图中,选择一个文件或者目录,使用右键,选择Team->Add to .cvsignore,一个对话框将会出现,你可以选择何种命名规则用于匹配被忽略的文件或目录。
资源修饰
当启用时此项,CVS 将用指示资源的 CVS 状态的图标和标号修饰来修饰“工作台”视图中的资源。
要启用 CVS 修饰:
1. 从主菜单栏,选择windows->preferences。
2. 在对话框中,选择Workbench->Label Decorations。此页面允许启用和禁用“工作台”中不同插件定义的所有修饰。
3. 选择 CVS 框以启用 CVS 修饰。
注意:某些情况下,修饰可能不会立即出现,原因是它们的计算成本很高。在这些情况下,将在后台计算它们。
我们也可以通过从选定的CVS资源库分支导入代码来创建新的工作台项目。首先,我们打开CVS资源库浏览视图(CVS Repository Exploring Perspective)。
我们能看到资源库里分支或版本下的CVS模块,一般我们都是导出HEAD分支下的CVS模块进行主开发流开发。
选择您希望导出的分支或版本项目,并从上下文菜单中选择Check Out As。
您可以选择把CVS模块导出为一个项目,例如下面,我们把HEAD分支下的NTT模块导出为NTT项目。如果工作台已经存在名称为NTT的项目,则用CVS模块覆盖已有的项目。
您也可以选择把CVS模块导出为某一工作台项目的一部分,例如我们把NTT模块导出到Prototype项目下的src目录下。但只有非共享项目或者与所选的远程文件夹共享同一 CVS 资源库的项目中的文件夹才是导出操作的有效目标。另外,如果操作的目标项目是一个非共享项目,Eclipse将把该项目连接至 CVS 资源库(例如,项目将成为共享 CVS 项目),但是将忽略先前存在的任何内容。