版本管理及WinCvs使用简介
1 概述
版本管理是程序开发、管理必不可少的工具,特别是在多人协作的团队中,适宜的版本管理工具可以提高开发效率,消除很多有代码版本带来的问题。一般来讲,版本管理工具能对软件开发过程中遇到的以下问题进行较好的控制:
1.代码管理混乱。
2.解决代码冲突。
3.在代码整合期间引入深层BUG。
4.无法对代码的拥有者进行权限控制。
5.项目不同版本发布困难。
目前我们维护的YH9000和YH9100两套PAS程序中,YH9000的代码总的来说比较混乱,而且各个现场版本之间差别很大,维护起来过于繁复,协同开发的效率也比较低下,以后我们将逐渐引入版本管理软件对YH9000的PAS部分进行管理,
2 主流版本管理软件介绍
现在的版本管理软件有很多,我对以下流行的软件进行了一些了解:
Starteam
是一个集合了版本控制、构建管理(Build Management)和缺陷跟踪系统为一体的软件,并且具有强大的图形界面,易学易用;但管理复杂、维护困难。2002年底被Borland公司收购。
PVCS Version Manager
是美国的MERANT公司软件配置管理工具PVCS 家族中的一个组成部分,它能够实现源代码、可执行文件、应用文件、图形文件和文档的版本管理;它能安全地支持软件并行开发,对多个软件版本的变更进行有效的控制管理。
ClearCase(CC)
是ROSE构件的一部分,目前最强大的配置管理工具,主要应用于复杂的产品发放、分布式团队合作、并行的开发和维护任务。可以控制word, excel,powerpoint,visio等文件格式,对于不认识的格式可以自己定义一种类型来标识。
Visual SourceSafe(VSS)
简单易用、方便高效、与Windows操作系统及微软开发工具高度集成。
CVS(Concurrent Versions System)
是开发源码的并发版本系统,它是目前最流行的面向软件开发人员的源代码版本管理解决方案。它可用于各种平台,包括 Linux 、Unix和 Windows NT/2000/XP等等。
前面三种是商业版本控制工具,都是非常昂贵的。Visual SourceSafe是微软的产品,只能用在windows平台并与微软的开发工具无缝集成。CVS免费开源,功能齐全,支持多种平台,重要的管理和使用比较简单,所以我们先选择这个软件进行版本管理的尝试。
3 CVS简介
CVS 是 Concurrent Version System(并行版本系统)的缩写,用于版本管理.如果大家曾经参与过多人协作开发的项目,大家肯定有这样的痛苦经历:由于多个人同时修改同一个文件,自己辛辛苦苦修改的程序被别人彻底删除了.另外,如果你的软件/程序已经发布了三个版本,而这时候用户需要你修改第二个版本的东西,也许你会因为只保留了最新版本而痛哭流涕。还有就是你对程序做了一些修改,但是修改很少,你只想给远方的同事发一个两个版本之间的差别文件,这样可以免于邮箱不够大,网速太慢之类的问题.为了解决类似这样的问题,以及诸如生成补丁文件,历史版本修改等,一帮黑客(褒义)在原先 Unix 体系里很成熟的 SCCS 和 RCS 的基础上,开发了 CVS。(SCCS:Source Code Control System,RCS:Revision Control System)。
CVS 的基本工作思路是这样的:在一台服务器上建立一个仓库,仓库里可以存放许多不同项目的源程序。由仓库管理员统一管理这些源程序.这样,就好象只有一个人在修改文件一样.避免了冲突.每个用户在使用仓库之前,首先要把仓库里的项目文件下载到本地。用户做的任何修改首先都是在本地进行,然后用 cvs 命令进行提交,由 cvs 仓库管理员统一 修改.这样就可以做到跟踪文件变化,冲突控制等等.
由于 CVS 是典型的 C/S 结构的软件,因此它也分成服务器端和客户端两部分。不过大多数CVS 软件都把它们合二为一了。我们这里就分别从服务器和客户端的角度讨论cvs的使用。
Cvs服务器安装
首先确保系统安装有cvs:
[*****************]#rpm-qa|grepcvs
cvs-1.11.1p1-3
如果命令输出类似于上面的输出则说明系统已经安装有cvs,否则就需要从安装光盘中安装cvs的rpm包。
一 创建CVS属主用户:
# useradd -d /cvsroot cvs
# chmod 771 /cv sroot
二、建立CVS仓库(初始化cvs)
# su cvs
$ cvs -d /cvsroot init
$exit
#
四、启动cvs服务器
在/etc/xinetd.d/目录下创建文件cvspserver,内容如下:
# default: on
# description: The cvs server sessions;
service cvspserver
{
socket_type = stream
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=/cvsroot pserver
log_on_failure += USERID
only_from = 192.168.0.0/24
}
其中only_from是用来限制访问的,可以根据实际情况不要或者修改。
修改该文件权限:
# chmod 644 cvspserver
然后重新启动xinetd:
# /etc/rc.d/init.d/xined restart
然后察看cvs服务器是否已经运行:
[*****************]#netstat-lnp|grep2401
tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 7866/xinetd
则说明cvs服务器已经运行。
五、创建用来访问cvs的用户
前面创建的cvs用户是cvs仓库管理用户,而为了让用户访问则还需要一个访问用户:
# useradd cvspub
# usemod -G cvs cvspub
这里添加了一个用户cvspub,并且将该用户添加到cvs组中。
六、管理cvs服务器
管理 cvs 服务器.服务器可以用了,现在大家最关心的就是如何管理服务器,比如,我想让一些人有读和/或写 CVS 仓库的权限,但是不想给它系统权限怎么办呢?不难,cvs初始化结束以后,在管理员用户(这里是cvs用户)的主目录里有一个 CVSROOT 目录,这个目录里有三个配置文件:passwd, readers, writers。我们可以通过设置这三个文件来配置 CVS 服务器,下面分别介绍这几个文件的作用:
passwd:cvs 用户的用户列表文件,它的格式很象 shadow 文件:
{cvs 用户名}:[加密的口令]:[等效系统用户名]
如果你希望一个用户只是 cvs 用户,而不是系统用户,那么你就要设置这个文件,刚刚安装完之后这个文件可能不存在,你需要以cvs管理员身份(su cvs)用户手工创建,当然要按照上面格式;
第二个字段是该用户的加密口令,就是用 crypt (3) 加密的,你可以自己写一个程序来做加密,也可以用两个偷懒的方法:先创建一个系统用户,名字和 cvs 用户一样,口令就是准备给它的 cvs 用户口令,创建完之后从 /etc/shadow 把该用户第二个字段拷贝过来,然后再把这个用户删除.这个方法对付数量少的用户比较方便,人一多就不合适了,而且还有冲突条件(race condition)的安全隐患,还要 root 权限,实在不怎么样,不过权
益之计而已;另外一个方法就是利用apche的htpasswd命令创建passwd用户,添加用户只需要htpasswd passwd username即可添加用户到passwd文件中,不过需要在文件中对应行的最后添加一个\":\"冒号和对应的等效系统用户名;最好的就是自己编写一个程序了来生成这个passwd文件了。
第三个字段就是等效系统用户名,实际上就是赋与一个 cvs 用户一个等效的系统用户的权限,看下面的例子你就明白它的功能了。
readers:有 cvs 读权限的用户列表文件,就是一个一维列表。在这个文件中的用户对 cvs
只有读权限。
writers:有 cvs 写权限的用户的列表文件,和 readers 一样,是一个一维列表。在这个文件中的用户对 cvs 有写权限。
上面三个文件在缺省安装的时候可能都不存在,需要我们自己创建,好吧,现在还是让我们用一个例子来教学吧.假设我们有下面几个用户需要使用 cvs:
cvsuser1, cvsuser2, henry, betty, anonymous
其中 laser 和 gumpwu 是系统用户,而henry, betty, anonymous 我们都不想给系统用户权限,并且 betty 和 anonymous 都是只读用户,而且 anonymous 更是连口令都没有。
然后编辑 cvs 管理员家目录里 CVSROOT/passwd 文件,加入下面几行:
laser:$xxefajfka;faffa33:cvspub
gumpwu:$ajfaal;323r0ofeeanv:cvspub
henry:$fajkdpaieje:cvspub
betty:fjkal;ffjieinfn/:cvspub
anonymous::cvspub
注意:上面的第二个字段(分隔符为 :)是密文口令,你要用程序或者用我的土办法生成。
编辑 readers 文件,加入下面几行:
anonymous
betty
编辑 writer 文件,加入下面几行:
laser
gumpwu
henry
这样就 ok 了,你再用几个用户分别登陆测试,就会发现一切都 ok 了。这里面的原理和说明我想就不多说了,其实很简单,和系统管理用户的概念是一样的。
4 CVS术语和缩写词
Repository:仓库,存储全部的版本管理下的文件拷贝,不容许直接访问,只能通过cvs命令,获得一份本地拷贝,改动后再check in(commit)回仓库。随着CVS版本的不同,文件的存放结构会发生变化,所以千万不要去直接访问仓库中的文件。我们目前CVS服务器上的仓库名为CVSRep;
Modules:模块,存放由软件管理的完整的项目,从物理上讲,模块是仓库的子目录;
Import:导入,本地的工作需要用CVS来管理,首先就需要将自己项目的整个目录结构导入到CVS的仓库中去,形成一个Module,现在我们已经把pas部分的整体的目录结构导入了;
Checkout:导出,将一个Module导出到本地的工作目录下,这样我们就可以开始在CVS的管理下工作了;
Commit:提交,我们在本地对工程中的文件进行修改之后,确认修改正确,需要更新CVS仓库中的文件,这个过程,就是Commit。可以Commit一个文件,也可以Commit 整个目录;
Update:同步,这个操作与Commit 相对应,是从仓库的Module中下载最新的文件,如果这个文件在本地也存在,就会更新本地的拷贝,如果本地没有,就会把新文件下
载到本地;
Revision:文件版本,CVS工作的机制就是通过版本号来管理文件的,一般来讲,1.1是所有文件的第一个版本,以后每修改一次,最右边的数字就加1,我们也可以将所有文件强制统一成一个我们指定的版本号;
Release:发行版本,整个产品的版本;
Tag:标签,用符号化的表示方法标志文件特定版本的信息。通常不需要对某一个孤立的文件作tag,而是对所有文件同时作一个tag,以后用户可以仅向特定tag的文件提交或者checkout,另外一个作用是在发布软件的时候表示哪些文件及其哪个版本是可用的,各文件不同revision可以包括在一个tag中,如果命名一个已存在的tag默认将不会覆盖原来的;
Branch:分支,在我们的开发需要兼顾不同的版本的时候,我们可以为一个工程创建一个分支,修改分支时不会影响到主线,并且我们可以在适当的时候对不同的分支进行合并,我觉得可以用来尝试管理不同现场版本的工程;
Conflct:冲突,指文件版本上的冲突。
5 CVS使用大全
一、CVS服务器的安装
首先确认系统中是否安装CVS服务:
[root@localhost /]# rpm -qa|grep cvs
cvs-1.11.2-cvshome.7x.1
如果命令输出类似于上面的输出则说明系统已经安装有cvs,否则就需要从安装光盘中安装cvs的rpm包,或者到http://www.cvshome.org下载。
1、建立 CVSROOT
目录,因为这里涉及到用户对CVSROOT里的文件读写的权限问题,所以比较简单的方法是建立一个组,然后再建立一个属于该组的帐户,而且以后有读写权限的用户都要属于该组。假设我们建一个组叫cvs,用户名是cvsroot。建组和用户的命令如下
#groupadd cvs
#useradd -g cvs -G cvs -d /home/cvsroot cvsroot
生成的用户宿主目录在/home/cvsroot(根据自己的系统调整)
2、建立CVS仓库,用cvsroot 用户登陆,用下面命令:
$cvs -d /home/cvsroot init
3、仍然是 cvsroot 用户,修改 /home/cvsroot (CVSROOT)的权限,赋与同组人有读写的权限:
$chmod 775 -R /home/cvsroot
4、用root登录,加入cvs服务(我的redhath7.3缺省就有cvs服务,所以不用加)
vi /etc/services
cvspserver 2401/tcp #pserver cvs service
cvspserver 2401/udp #pserver cvs service
cvs服务由inted来唤起,因此需要改动inetd提供的服务,如果你的redhat使用的是inetd 方式则在文件/etc/inetd.conf中加入如下的内容:cvspserver stream tcp nowait root /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver
我的redhat7.3使用的是xinetd方式,所以在xinetd.d目录下添加需要启动的服务:
cd /etc/xinetd.d
vi cvspserver
文件内容:
service cvspserver
{
disable = no
flags = REUSE
socket_type = stream
wait = no
user = cvsroot
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvsroot pserver
log_on_failure += USERID
}
重新启动inetd或者xinetd:
/etc/rc.d/init.d/xinetd restart
检查cvspserver服务是否已经启动
[root@localhost /]# netstat -lnp|grep 2401
tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 1041/xinetd
则说明cvs服务器已经运行。
二、管理CVS服务器
服务器可以用了,现在大家最关心的就是如何管理服务器,比如,我想让一些人有读和/或写 CVS 仓库的权限,但是不想给它系统权限怎么办呢?
不难,在 cvs 管理员用户(在我这里是 cvsroot 用户)的家目录里有一个 CVSROOT 目录,这个目录里有三个配置文件,passwd, readers, writers,我们可以通过设置这三个文件来配置 CVS 服务器,下面分别介绍这几个文件的作用:
passwd:cvs 用户的用户列表文件,它的格式很象 shadow 文件:
{cvs 用户名}:[加密的口令]:[等效系统用户名]
readers:有 cvs 读权限的用户列表文件。就是一个一维列表。在这个文件中的用户对 cvs只有读权限。
writers:有 cvs 写权限的用户的列表文件。和 readers 一样,是一个一维列表。在这个文件中的用户对 cvs 有写权限。
上面三个文件在缺省安装的时候可能都不存在,需要我们自己创建,好吧,现在还是让我们用一个例子来教学吧。假设我们有下面几个用户需要使用 cvs:
laser, gumpwu, henry, betty, anonymous。
其中 laser 和 gumpwu 是系统用户,而 henry, betty, anonymous 我们都不想给系统用户权限,并且 betty 和 anonymous 都是只读用户,而且 anonymous 更是连口令都没有。
然后编辑 cvs 管理员家目录里 CVSROOT/passwd 文件(cvsroot用户),加入下面几行:
laser:$xxefajfka;faffa33:cvsroot
gumpwu:$ajfaal;323r0ofeeanv:cvsroot
henry:$fajkdpaieje:cvsroot
betty:fjkal;ffjieinfn/:cvsroot
anonymous::cvsroot
注意:上面的第二个字段(分隔符为 :)是密文口令。
密码可以有以下方法生成
vi /home/cvsroot/passwdgen.pl
文件内容:
#!/usr/bin/perl
srand (time());
my $randletter = \"(int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97))\";
my $salt = sprintf (\"%c%c\
my $plaintext = shift;
my $crypttext = crypt ($plaintext, $salt);
print \"${crypttext}\\n\";
如果需要密码为:some,则敲入:
./passwdgen.pl some
(注意passwdgen.pl要先设为可执行)
回车即可得到加密密码,用其替换passwd文件中的passwd部分就可以了
编辑 readers 文件,加入下面几行:
anonymous
betty
编辑 writers 文件,加入下面几行:
laser
gumpwu
henry
注意:writers中的用户不能在readers中,要不然不能上传更新文件。
对于使用CVS的用户要修改它的环境变量,例如laser用户的环境变量,打开/home/laser(laser的宿主目录)下的.bash_profile文件,加入
CVSROOT=/home/cvsroot
export CVSROOT
用laser登陆就可以建立CVS项目,如果要root使用,可以修改/etc/profile文件。
现在我们各项都设置好了,那么怎么用呢,我在这里写一个最简单的(估计也是最常用的)命令介绍:
首先,建立一个新的CVS项目,一般我们都已经有一些项目文件了,这样我们可以用下面步骤生成一个新的CVS项目:
进入到你的已有项目的目录,比如叫 cvstest:
$cd cvstest
运行命令:
$cvs import -m \"this is a cvstest project\" cvstest v_0_0_1 start
说明:import 是cvs的命令之一,表示向cvs仓库输入项目文件。 -m参数后面的字串是描述文本,随便写些有意义的东西,如果不加 -m 参数,那么cvs会自动运行一个编辑器(一般是vi,但是可以通过修改环境变量EDITOR来改成你喜欢用的编辑器。)让你输入信息,cvstest 是项目名称(实际上是仓库名,在CVS服务器上会存储在以这个名字命名的仓库里。)
v_0_0_1是这个分支的总标记。没啥用(或曰不常用。)
start 是每次 import 标识文件的输入层次的标记,没啥用。
这样我们就建立了一个CVS仓库了。
建立CVS仓库的文件夹应该是“干净”的文件夹,即只包括源码文件和描述的文件加,而不应该包括编译过的文件代码等!
三.CVS环境初始化
============
环境设置:指定CVS库的路径CVSROOT
tcsh
setenv CVSROOT /path/to/cvsroot
bash
CVSROOT=/path/to/cvsroot ; export CVSROOT
后面还提到远程CVS服务器的设置:
CVSROOT=:ext:$****************.address#port:/path/to/cvsrootCVS_RSH=ssh; export CVSROOT CVS_RSH
初始化:CVS版本库的初始化。
cvs init
一个项目的首次导入
cvs import -m \"write some comments here\" project_name vendor_tag release_tag
执行后:会将所有源文件及目录导入到/path/to/cvsroot/project_name目录下
vender_tag: 开发商标记
release_tag: 版本发布标记
项目导出:将代码从CVS库里导出
cvs checkout project_name
cvs 将创建project_name目录,并将最新版本的源代码导出到相应目录中。这个checkout和Virvual SourceSafe中的check out不是一个概念,相对于Virvual SourceSafe的check out是cvs update, check in是cvs commit。
四.CVS的日常使用
=============
注意:第一次导出以后,就不是通过cvs checkout来同步文件了,而是要进入刚才cvs checkout project_name导出的project_name目录下进行具体文件的版本同步(添加,修改,删除)操作。
将文件同步到最新的版本
cvs update
不制定文件名,cvs将同步所有子目录下的文件,也可以制定某个文件名/目录进行同步
cvs update file_name
最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次,并养成“先同步 后修改”的习惯,和Virvual SourceSafe不同,CVS里没有文件锁定的概念,所有的冲突是在commit之前解决,如果你修改过程中,有其他人修改并commit到了CVS库中,CVS会通知你文件冲突,并自动将冲突部分用
>>>>>>
content on cvs server
<<<<<<
content in your file
>>>>>>
标记出来,由你确认冲突内容的取舍。
版本冲突一般是在多个人修改一个文件造成的,但这种项目管理上的问题不应该指望由CVS来解决。
确认修改写入到CVS库里
cvs commit -m \"write some comments here\" file_name
注意:CVS的很多动作都是通过cvs commit进行最后确认并修改的,最好每次只修改一个文件。在确认的前,还需要用户填写修改注释,以帮助其他开发人员了解修改的原因。如果不用写-m \"comments\"而直接确认`cvs commit file_name` 的话,cvs会自动调用系统缺省的文字编辑器(一般是vi)要求你写入注释。
注释的质量很重要:所以不仅必须要写,而且必须写一些比较有意义的内容:以方便其他开发人员能够很好的理解
不好的注释,很难让其他的开发人员快速的理解:比如: -m \"bug fixed\" 甚至 -m \"\"
好的注释,甚至可以用中文: -m \"在用户注册过程中加入了Email地址校验\"
修改某个版本注释:每次只确认一个文件到CVS库里是一个很好的习惯,但难免有时候忘了指定文件名,把多个文件以同样注释commit到CVS库里了,以下命令可以允许你修改某个文件某个版本的注释:
cvs admin -m 1.3:\"write some comments here\" file_name
添加文件
创建好新文件后,比如:touch new_file
cvs add new_file
注意:对于图片,Word文档等非纯文本的项目,需要使用cvs add -b选项按2进制文件方式导入,否则有可能出现文件被破坏的情况
比如:
cvs add -b new_file.gif
cvs add -b readme.doc
然后确认修改并注释
cvs ci -m \"write some comments here\"
删除文件
将某个源文件物理删除后,比如:rm file_name
cvs rm file_name
然后确认修改并注释
cvs ci -m \"write some comments here\"
以上面前2步合并的方法为:
cvs rm -f file_name
cvs ci -m \"why delete file\"
注意:很多cvs命令都有缩写形式:commit=>ci; update=>up; checkout=>co/get; remove=>rm;
添加目录
cvs add dir_name
查看修改历史
cvs log file_name
cvs history file_name
查看当前文件不同版本的区别
cvs diff -r1.3 -r1.5 file_name
查看当前文件(可能已经修改了)和库中相应文件的区别
cvs diff file_name
cvs的web界面提供了更方便的定位文件修改和比较版本区别的方法,具体安装设置请看后面的cvsweb使用
正确的通过CVS恢复旧版本的方法:
如果用cvs update -r1.2 file.name
这个命令是给file.name加一个STICK TAG: \"1.2\" ,虽然你的本意只是想将它恢复到1.2版本
正确的恢复版本的方法是:cvs update -p -r1.2 file_name >file_name
如果不小心已经加成STICK TAG的话:用cvs update -A 解决
移动文件/文件重命名
cvs里没有cvs move或cvs rename,因为这两个操作是可以由先cvs remove old_file_name,然后cvs add new_file_name实现的。
删除/移动目录
最方便的方法是让管理员直接移动,删除CVSROOT里相应目录(因为CVS一个项目下的子目录都是独立的,移动到$CVSROOT目录下都可以作为新的独立项目:好比一颗树,其实砍下任意一枝都能独立存活),对目录进行了修改后,要求其开发人员重新导出项目cvs checkout project_name 或者用cvs update -dP同步。
项目发布导出不带CVS目录的源文件
做开发的时候你可能注意到了,每个开发目录下,CVS都创建了一个CVS/目录。里面有文件用于记录当前目录和CVS库之间的对应信息。但项目发布的时候你一般不希望把文件目录还带着含有CVS信息的CVS目录吧,这个一次性的导出过程使用cvs export命
令,不过export只能针对一个TAG或者日期导出,比如:
cvs export -r release1 project_name
cvs export -D 20021023 project_name
cvs export -D now project_name
五.CVS Branch:项目多分支同步开发
=============================
确认版本里程碑:多个文件各自版本号不一样,项目到一定阶段,可以给所有文件统一指定一个阶段里程碑版本号,方便以后按照这个阶段里程碑版本号导出项目,同时也是项目的多个分支开发的基础。
cvs tag release_1_0
开始一个新的里程碑:
cvs commit -r 2 标记所有文件开始进入2.x的开发
注意:CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。
版本分支的建立
在开发项目的2.x版本的时候发现1.x有问题,但2.x又不敢用,则从先前标记的里程碑:release_1_0导出一个分支release_1_0_patch
cvs rtag -b -r release_1_0 release_1_0_patch proj_dir
一些人先在另外一个目录下导出release_1_0_patch这个分支:解决1.0中的紧急问题,
cvs checkout -r release_1_0_patch
而其他人员仍旧在项目的主干分支2.x上开发
在release_1_0_patch上修正错误后,标记一个1.0的错误修正版本号
cvs tag release_1_0_patch_1
如果2.0认为这些错误修改在2.0里也需要,也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中:
cvs update -j release_1_0_patch_1
六.CVS的远程认证:通过SSH远程访问CVS
================================
使用cvs本身基于pserver的远程认证很麻烦,需要定义服务器和用户组,用户名,设
置密码等,
常见的登陆格式如下:
cvs-d:pserver:************************.address:/path/to/cvsrootlogin
例子:
cvs-d:pserver:*************:/cvsrootlogin
不是很安全,因此一般是作为匿名只读CVS访问的方式。从安全考虑,通过系统本地帐号认证并通过SSH传输是比较好的办法,通过在客户机的/etc/profile里设置一下内容:
CVSROOT=:ext:$***************.address#port:/path/to/cvsrootCVS_RSH=ssh; export CVSROOT CVS_RSH
所有客户机所有本地用户都可以映射到CVS服务器相应同名帐号了。
比如:
CVS服务器是192.168.0.3,上面CVSROOT路径是/home/cvsroot,另外一台开发客户机是192.168.0.4,如果tom在2台机器上都有同名的帐号,那么从192.168.0.4上设置了:
exportCVSROOT=:ext:***********.0.3:/home/cvsroot
export CVS_RSH=ssh
tom就可以直接在192.168.0.4上对192.168.0.3的cvsroot进行访问了(如果有权限的话)
cvs checkout project_name
cd project_name
cvs update
...
cvs commit
如果CVS所在服务器的SSH端口不在缺省的22,或者和客户端与CVS服务器端SSH缺省端口不一致,有时候设置了:
:ext:$****************.address#port:/path/to/cvsroot
仍然不行,比如有以下错误信息:
ssh: test.server.address#port: Name or service not known
cvs [checkout aborted]: end of file from server (consult above messages if any)
解决的方法是做一个脚本指定端口转向(不能使用alias,会出找不到文件错误):
创建一个/usr/bin/ssh_cvs文件:
#!/usr/bin/sh
/path/to/ssh -p 34567 \"$@\"
然后:chmod +x /usr/bin/ssh_cvs
并CVS_RSH=ssh_cvs; export CVS_RSH
注意:port是指相应服务器SSH的端口,不是cvs pserver的端口。
七.CVSWEB:提高文件浏览效率
=======================
CVSWEB就是CVS的WEB界面,可以大大提高程序员定位修改的效率:
使用的样例可以看:http://www.freebsd.org/cgi/cvsweb.cgi
CVSWEB的下载:CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本,这个是我个人感觉安装设置比较方便的:
http://www.spaghetti-code.de/software/linux/cvsweb/
下载解包:
tar zxf cvsweb.tgz
把配置文件cvsweb.conf放到安全的地方(比如和apache的配置放在同一个目录下),
修改:cvsweb.cgi让CGI找到配置文件:
$config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';
转到/path/to/apache/conf下并修改cvsweb.conf:
1. 修改CVSROOT路径设置:
%CVSROOT = (
'Development' => '/path/to/cvsroot', #<==修改指向本地的CVSROOT
);
2. 缺省不显示已经删除的文档:
\"hideattic\" => \"1\缺省不显示已经删除的文档
3. 在配置文件cvsweb.conf中还可以定制页头的描述信息,你可以修改$long_intro
成你需要的文字
CVSWEB可不能随便开放给所有用户,因此需要使用WEB用户认证:
先生成 passwd:
/path/to/apache/bin/htpasswd -c cvsweb.passwd user
修改httpd.conf: 增加
AuthName \"CVS Authorization\" AuthType Basic AuthUserFile /path/to/cvsweb.passwd require valid-user
八.CVS TAGS: who? when?
====================
将$Id$ 加在程序文件开头的注释里是一个很好的习惯,cvs能够自动解释更新其中的内容成:file_name version time user_name 的格式,比如:cvs_card.txt,v 1.1 2002/04/05 04:24:12 chedong Exp,可以这些信息了解文件的最后修改人和修改时间
几个常用的缺省文件:
default.php
/*
* Copyright (c) 2002 Company Name.
* $Header$
*/
>
====================================
Default.java: 注意文件头一般注释用 /* 开始 JAVADOC注释用 /** 开始的区别
/*
* Copyright (c) 2002 MyCompany Name.
* $Header$
*/
package com.mycompany;
import java.;
/**
* comments here
*/
public class Default {
/**
* Comments here
* @param
* @return
*/
public toString() {
}
}
====================================
default.pl:
#!/usr/bin/perl -w
# Copyright (c) 2002 Company Name.
# $Header$
# file comments here
use strict;
九.WinCVS
======
下载:
cvs Windows客户端:目前稳定版本为1.2
http://www.wincvs.org/
ssh Windows客户端
http://www.networksimplicity.com/openssh/
安装好以上2个软件以后:
WinCVS客户端的admin==>preference设置
1 在general选单里
设置CVSROOT: ****************.0.123:/home/cvsroot
设置Authorization: 选择SSH server
2 Port选单里
钩上:check for alternate rsh name
并设置ssh.exe的路径,缺省是装在 C:Program FilesNetworkSimplicitysshssh.exe
然后就可以使用WinCVS进行cvs操作了,所有操作都会跳出命令行窗口要求你输入服务器端的认证密码。
当然,如果你觉得这样很烦的话,还有一个办法就是生成一个没有密码的公钥/私钥对,并设置CVS使用基于公钥/私钥的SSH认证(在general选单里)。
可以选择的diff工具:examdiff
下载:
http://www.prestosoft.com/examdiff/examdiff.htm
还是在WinCVS菜单admin==>preference的WinCVS选单里
选上:Externel diff program
并设置diff工具的路径,比如:C:Program Filesed16iExamDiff.exe
在对文件进行版本diff时,第一次需要将窗口右下角的use externel diff选上。
十.基于CVS的小组开发环境搭建
========================
作为一个小组级的开发环境,版本控制系统和BUG跟踪系统等都涉及到用户认证部分。如何方便的将这些系统集成起来是一个非常有趣的事情,毕竟我们不能指望linux下
有像Source Offsite那样集成度很高的版本控制/BUG跟踪集成系统。
我个人是很反对使用pserver模式的远程用户认证的,但如果大部分组员使用WINDOWS客户端进行开发的话,总体来说使用CVSROOT/passwd认证还是很难避免的,但CVS用户的管理比较麻烦。本来我打算自己用perl写一个管理界面的,直到我发现了CVSTrac, 一个基于WEB界面的BUG跟踪系统,它外挂在CVS系统上,而且就包括了WEB界面的CVSROOT/passwd文件的管理,甚至还集成了WIKIWIKI功能。
这里首先说一下CVS的pserver模式下的用户认证,CVS的用户认证服务是基于inetd中的:
cvspserver stream tcp nowait nobody /usr/bin/cvs cvs
--allow-root=/home/cvsroot pserver
一般在2401端口
CVS用户数据库是基于CVSROOT/passwd文件,文件格式:
[username]:[crypt_password]:[mapping_system_user]
由于密码都用的是UNIX标准的CRYPT加密,这个passwd文件的格式基本上是apache的htpasswd格式的扩展(比APACHE的PASSWD文件多一个系统用户映射字段),所以这个文件最简单的方法可以用
apache/bin/htpasswd -b myname mypassword
创建。注意:通过htpasswd创建出来的文件会没有映射系统用户的字段
例如:
new:geBvosup/zKl2
setup:aISQuNAAoY3qw
test:hwEpz/BX.rEDU
映射系统用户的目的在于:你可以创建一个专门的CVS服务帐号,比如叫cvs,并将/home/cvsroot目录下的所有权限赋予这个用户,然后在passwd文件里创建不同的开发用户帐号,但开发用户帐号最后的文件读写权限都映射为cvs用户,避免了在SSH模式下多个开发用户新建文件后的对于其他用户的文件读写权限问题。
进一步的,你可以将用户分别映射到2组用户上,利用2个用户的权限设置,避免2个项目组的文件互相访问。
new:geBvosup/zKl2:proj1
setup:aISQuNAAoY3qw:proj2
test:hwEpz/BX.rEDU:proj1
CVSTrac很好的解决了CVSROOT/passwd的管理问题,而且包含了BUG跟踪报告系统和集成WIKIWIKI交流功能等,使用的CGI方式的安装,并且基于GNU Public
License:
安装过程
1. 下载:http://www.cvstrac.org 解包,复制成/usr/bin/cvstrac
2. 在已经装好的CVS服务器上(假设CVS库已经使用cvs init初始化过在/home/cvsroot里),运行一下
cvstrac init /home/cvsroot myproj
运行后,/home/cvsroot里会有一个缺省的myproj.db库
3. 在apche/cgi-bin目录中创建如下脚本cvstrac:
#!/bin/sh
/usr/bin/cvstrac cgi /home/cvsroot
设置cvstrac可执行。
4. 从http://cvs.server.address/cgi-bin/cvstrac/myproj进入管理界面,缺省登录名:setup 密码 setup
5. 在inetd里加入cvspserver服务:
cvspserver stream tcp nowait nobody /usr/bin/cvs cvs
--allow-root=/home/cvsroot pserver
注意:这里的用户设置成nobody目的是和apache的运行用户一致,并且必须让这个这个用户对/home/cvsroot/下的CVSROOT/passwd和cvstrac初始化生成的myproj.db有读写权限。
一般用户还可以从:
http://cvs.server.address/cgi-bin/cvstrac/myproj
修改登录密码,记录BUG报告等,更多使用细节可以在使用中慢慢了解。
对于前面提到的WinCVS改用passwd file on server side模式登录就可以了。
总结:
利用cvs + (WinCVS/cvsweb/cvstrac),构成了一个相对完善的跨平台工作组开发环境。
6 WinCvs的安装与配置
安装
目前我们使用的客户端是WinCvs1.3.17.1(Beta 17),以后可能要换成新版本或别的软件,先使用这个进行熟悉,到cvsserver(10.6.2.129)上去找到这个版本的安装文件,
同时还需要安装python语言,版本为2.3.4,将这两个软件在本地安装好即可。
配置
在使用WinCvs之前,我们需要对CVSROOT变量进行配置,启动WinCvs程序,点击菜单”Admin->Preferences”,将弹出对话框:
CVSROOT变量不需要手工输入,只要填好前面的选项即可,上面的截图是General属性页的配置:
Authentication:认证方式,现在提供pserver方式;
Path:仓库路径;
Host address:服务器地址;
User name:用户名。
Globals属性页可以使用缺省属性。
CVS属性页配置如下:
HOME:指定存放一些客户端临时信息的目录;
Alternate CVS executable:如果使用WinCvs作为CVS服务器来管理本地的项目,则需要选中此选项并进行设置;
Show CVS console:是否显示CVS的控制台;
WinCvs属性页配置如下:
External diff:指定你使用的文件差异比较工具;
Default:指定你使用的文本编辑工具;
Python和TCL DLL指定使用的Python和TCL脚本语言的安装位置,已经在path环境变量中写好了,不需要设置;
Folders:存放设置信息的目录,缺省即可。
做了这些配置以后,就可以开始使用WinCvs了。
7 常用功能
import modules:启动WinCvs,点击”View->Browse location change”将浏览目录指定到本地的工作目录,选中要导入的工作目录,点击”Remote->Import module”或点击右键菜单”Import module”,WinCvs会检测目录中的文件类型,并
弹出确认窗口
如果WinCvs缺省确认的文件类型有错误,可以使用”Edit”来修改。确认文件类型之后,会弹出导入模块的设置窗口
这里可以保留缺省设置(Import settings中可以设置保存到仓库中的module的名称、初始版本的标签、初始日志信息等等),如果WinCvs的参数配置正确的话,General中的信息也可以采用缺省设置,我们已经将YH9000的pas代码导入仓库了,也为ots和dts用户建立了空的module,一般来说pas用户不需要做这种导入操作了,确实要添加自己的新目录时,要使用Add方法,不要打乱了服务器上的目录结构(使用Import module将会在CVS服务器上建立新的module,这种做法是不提倡的);
checkout modules:启动WinCvs,在目录浏览窗口中选中本地目录(准备用来存放导出的module的目录),点击”Remote->Checkout module”或者点击右键菜单”Checkout module”,会弹出checkout的设置窗口
对于普通操作来说,其它属性页都可以使用缺省选项,Checkout settings中需要注意一下,在Module name and path on the server中,需要填写module名称或者某一个子目录的路径(点击后面的浏览按钮可以看到目前我们仓库中存在的三个模块dts、ots、pas),如果要checkout一个子目录,例如截图中的”include”,你需要知道具体的目录结构是什么样的(初次使用的时候需要checkout整个模块,以后一般不需要进行这种操
作了)。Check out into direction选项是设置保存到本地以后的路径的,在上面的截图中,最终checkout出来的include将会放在” E:\\cvsClient\\pas\\src\\yh9000\\”下,注意不要弄错了;
update selection:选中一个或多个目录或文件,点击”Modify->Update selection”或右键菜单或快捷键或工具栏图标,确认Update即可;
commit selection:选中要commit的目录或文件,点击”Modify->commit”或右键菜单或快捷键或工具栏图标,会弹出commit设置窗口
在Commit settings属性页中可以填写修改日志(最好养成这种习惯),在Commit options属性页中有一个Force commit选项,如果你要提交的文件没有进行任何改动(文件浏览窗口可以看到如果文件有改动,图标会变成红色的),而又想提交上去的话,可以选中这个选项,设置完毕,确认即可;
add selection:当在开发中添加新的文件或者目录的时候,需要先add这个文件或
目录,点击”Modify->Add selection”或工具栏图标先添加,再commit(有可能在WinCvs的文件列表窗口看不到新添加的文件,那是因为在” View->File Filter”选项中隐藏了unknown的文件),注意在添加目录的时候,目录和子目录中的文件并没有添加进去,需要一个个手工add;
删除文件:选中要删除的文件,点击”Modify”可以看到有两个删除命令:remove和erase selection,前者删除本地和服务器上的文件(使用完了以后需要commit才会生效),后者只删除本地文件;
删除目录:只能到仓库中手工删除,建议不要做这种操作,在add的时候要确认是一个有效的版本;
查看文件的版本历史:选中要查看的文件,点击” Query->Graph”或右键菜单”Graph selection”,确认设置窗口即可;
查看文件的版本差异:显示文件的版本历史图,选中两个要比较的版本(使用Ctrl键),点击” Graph->Diff selected”或右键菜单”Diff selected”,确认即可;
提取旧版本的文件:显示文件的版本历史图,点击右键菜单”Retrieve revision as”,起个新的文件名即可;
从文件的某个版本重新开始:如果从仓库中最新的版本更新,直接选择Update selection就可以了,如果是从旧版本开始,需要在Update设置窗口对中填写以下的信息
选择Update Option属性页,选中Retrieve rev./tag/bran并填写版本号,确定即可;
统一版本:一般在开发到了一个特定的阶段(比如说出现了一个稳定的版本),就需要对整个工程统一一个版本号,在commit的设置窗口中填写以下的信息
选择Commit options属性页,选中Force revision/branch并填写想要统一的版本
号,确定即可,这个时候版本号已经被更新了,但是同时所有文件也被打上了一个tag,需要重新Update(选中Update setting->Reset any sticky date/tag/’-k’ options选项)一下,以免影响到以后的commit。注意,统一版本号的操作只能在所有的文件都不是初始版本的时候才允许做统一,如果有文件仍然是1.1版,事先需要强制commit一下,更新其版本号;
创建标签:在开发到了特定的阶段,需要对整个项目创建一个标签以便于是别,一般不会对单个文件加上标签,选择要创建标签的项目(或文件),点击”Modify->Create a tag on selection”
填写标签名称确认即可,需要注意的是,Tag只能是由数字、字母、’ -’和’ _’组成,并且以字母开头,Tag不单单只是版本的别名,我们还可以使用它在Update或者Checkout的时候选择特定Tag的版本;
创建分支:选择要创建分支的目录,点击”Modify->Create a branch”
填写分支名称(要求与Tag一致),确认即可,最好把Check that the files are unmodified before branching选项选上;
进入分支工作:进入分支工作之前,需要先清除主线文件,而把分支文件下载到本地来,在Update settings中选中Create missing directories that exist in the repository选项,同时要在Update options中选上Retrieve rev./tag/branch,填好分支名称,确认即可;
从分支回到开发主线:要分两种情况来考虑,一种是要把分支的工作带回主线工作(称之为Merge),一种是不带回主线,回到主线的操作按以下的步骤进行:
1.选中Update settings的Create missing directories that exist int the repository和Reset any sticky date//tag/’-k’ options,如果不想把分支的工作带回主线,直接确定即可;
2.在Merge option中选择Only this rev./tag,并填写要merge的分支的名字
确认;
3.这时候将会输出Merging differences between x.x and x.x.x.x into XXX.cpp,这表示已经把分支(x.x.x.x)的工作融合到主线(x.x)中去了
commit一下,就会形成新的主线版本——该文件的版本历史图中将会出现一根红线
如果没有Merge,则不会有这根红线;
生成项目的ChangeLog:ChangeLog是一个描述模块或文件变化历史的文本,生成步骤如下:Macros->CVS->Build ChangeLog,也可以使用Query->Log…来查询。
8 CVS使用注意事项
1.工作之前Update,取得当前公共文件的最新版本;
2.确认修改有效之后Commit,不要把临时的或者不能用的文件提交到服务器上,在要提交的文件发生冲突之后,先找相关人员解决冲突以后再提交,不要养成强制commit的习惯;
3.一般来说不要进行Import module操作,不要在仓库中私自新建模块,需要Add新的目录时要注意路径,不要打乱服务器上的目录结构;
4.因为CVS不支持更名,一旦名称改变,所有的历史版本信息将会丢失,所以在使用的时候不要随意更改你的目录或文件的名称;
5.管理好本机上的工作目录,其中隐藏的CVS目录中存放了你使用的用户的信息,如果对他们进行删改或者从别的同事的机器上拷贝,可能会造成你以后的操作出错;
6.在初次使用的时候将你工作需要的整个module都checkout出来,在以后的工作中最好只做Update操作,确实需要checkou模块中的某个子目录,注意填写路径信息,不要打乱了本机上的目录结构;
7.目前的CVS服务器ip为10.6.2.129,仓库名为F:/CVSRep,已经创建了dts、ots、pas三个module,其中pas部分已经上传了代码,大家可以用来熟悉操作,在我们正式启用CVS之后,最好不要再进行test类型的操作了;
8.启用CVS的目的在于增强我们的版本管理的意识,如果以后有更合适的工具,我们也可以采用。
因篇幅问题不能全部显示,请点此查看更多更全内容