快捷搜索:

并行版本系统 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 软件都把它们合二为一了。

结合文档和一些网上资本,我写一点异常简单的“速成”的课本.盼望对大年夜家有用.

下面是我的步骤和做法:

条件要求:

root 权限;

CVS软件,请找到相关的rpm,tgz,deb 等包装上,或者到

http://www.cvshome.org/CVS/Dev/code

下载原法度榜样编译安装,这里我不准备先容它的安装,请参考CVS自身的文档安装.我应用Slackware的tgz包,安装的敕令是

#installpkg cvs*.tgz

其他包请参考对应担保理对象的敕令.

必然的系统资本,要有必然内存(32M就能事情得很好),要必然的磁盘空间,看你的项目的大年夜小和若干而定. 架设CVS办事器:

建立 CVSROOT 目录,由于这里涉及到用户对CVSROOT里的文件读写的权限问题,以是对照简单的措施是建立一个组,然后再建立一个属于该组的帐户,而且今后有读写权限的用户都要属于该组.假设我们建一个组叫cvs,用户名是cvsroot.建组和用户的敕令如下

#groupadd cvs

#adduser cvsroot

天生的用户家目录在/home/cvsroot(根据自己的系统调剂)

用 cvsroot 用户登岸,改动 /home/cvsroot (CVSROOT)的权限,赋与同组人有读写的权限:

$chmod 771 . (或者770应该也可以)

留意:这一部分事情是按照文档阐明做的,是否必然必要这样没有试验,我会在做试验后在今后版本的教程说得仔细一点.假如您有这方面的履历请供给给我,感谢.

建立CVS仓库,(仍旧是 cvsroot 用户),用下面敕令:

$cvs-d /home/cvsroot init

以root身份登岸,改动 /etc/inetd.conf(应用 xinetd 的系统没有此文件)和 /etc/services,

假如用的是 inetd 的系统,在 /etc/inetd.conf 里加入:

cvsserverstreamtcpnowaitroot/usr/bin/cvscvs -f--allow-root=/home/cvsroot pserver

阐明:上面的行是零丁一整行,/usr/bin/cvs 应该是你的cvs版本的敕令路径,请根据自己的系统调剂./home/cvsroot 是你建立的CVSROOT的路径,也请根据上面建立目录的部分的内容做调剂.

假如是应用 xinetd 的系统,必要在 /etc/xinetd.d/ 目录下创建文件 cvspserver(此名字可以自己定义),内容如下:

# default: on

# description: The cvs server sessions;

service cvsserver

{

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

在/etc/services里加入:

cvsserver2401/tcp

阐明:cvsserver 是随意率性的名称,然则不能和已有的办事重名,也要和上面改动 /etc/inetd.conf 那行的第一项同等.这里我用的是 CVS 的口令认证要领,CVS 还有其他认证要领,我没有做试验,假如您有履历,请弥补,感谢.

添加可以应用 CVS 办事的用户到 cvs 组:

以 root 身份改动 /etc/group,把必要应用 CVS 的用户名加到 cvs 组里,比如我想让用户 laser 和gumpwu 能够应用 CVS 办事,那么改动今后的 /etc/group 应该有下面这样一行:

cvs:x:105:laser,gumpwu

在你的系统上GID可能不是105,没有关系.主如果要把laser和gumpwu用逗号分隔开写在着末一个冒号后面.当然,象RedHat中分发版有类似linuxconf这样的对象的话,用对象做这件事会更简单些.

重起inetd使改动生效:

#killall -HUP inetd

假如应用的是 xinetd 的系统:

# /etc/rc.d/init.d/xined restart

这样办事器就设置完成了.我们接着搞客户端.

设置客户端

假如是 Linux(或者其他 *nix),客户端和办事器真个软件是一样的,假如是Win,MAC等平台,请到

http://www.loria.fr/cgi-bin/molli/wilma.cgi/rel

找响应的客户端软件,这里我先说一下在 Linux(*nix)里怎么做:

设置情况变量CVSROOT:

$export CVSROOT=:pserver:laser@the_server_name:/home/cvsroot

留意:这里的pserver是造访要领,我在上面设置的是口令认证,以是这里是pserver,假如你的CVS办事器设置成其余造访模式,那么必要响应改动.laser是可以应用 CVS办事器的用户名,这里可以根据你的设置改动,我在这个版本设置的是直接应用系统用户的口令文件,也便是说laser必须是CVS办事器上的合法用户,这里当然有安然问题,CVS可以设置成为拥有自己的用户,我将在今后的版本里面增添这些内容,或者您也可以供给一些弥补,或者直接读CVS的文档.the_server_name是CVS办事器的名称或者IP地址,根据你的环境填写,/home/cvsroot是你的CVS办事器的CVSROOT目录,根据你的CVS办事器设置做改动或者扣问治理员.你可以把这行放到你的shell的profile里(.bash_profile,.profile等)这样就不用每次敲一长串敕令了.

登岸CVS办事器:

$ cvs login,这时刻 cvs 会问你口令,请把你在 CVS 办事器上的口令敲进去,这里是 laser 在 CVS办事器上的系统用户的口令:

Passwd:xxxxxxxx

成功登岸后将在你的家目录建立一个 .cvspass 文件,今后就不用输进口令了.

好,客户端设置完成,简单吧.

治理 cvs 办事器

办事器可以用了,现在大年夜家最关心的便是若何治理办事器,比如,我想让一些人有读和/或写 CVS 仓库的权限,然则不想给它系统权限怎么办呢?

不难,在 cvs 治理员用户(在我这里是 cvsroot 用户)的家目录里有一个 CVSROOT 目录,这个目录里有三个设置设置设备摆设摆设文件,passwd, readers, writers,我们可以经由过程设置这三个文件来设置设置设备摆设摆设 CVS 办事器,下面分手先容这几个文件的感化:

passwd:cvs 用户的用户列表文件,它的款式很象 shadow 文件:

{cvs 用户名}:[加密的口令]:[等效系统用户名]

假如你盼望一个用户只是 cvs 用户,而不是系统用户,那么你就要设置这个文件,刚刚安装完之后这个文件可能不存在,你必要以 cvs 治理员用户手工创建,当然要按照上面款式,第二个字段是该用户的加密口令,便是用 crypt (3) 加密的,你可以自己写一个法度榜样来做加密,也可以用我先容的偷懒的措施:先创建一个系统用户,名字和 cvs 用户一样,口令便是筹备给它的 cvs 用户口令,创建完之后从 /etc/shadow 把该用户第二个字段拷贝过来,然后再把这个用户删除.这个措施对于数量少的用户对照方便,人一多就分歧适了,而且还有冲突前提(race condition)的安然隐患,还要 root 权限,其实不怎么样.不过职权之计而已.写一个小法度榜样并不难,可以到 linuxforum 的编程版搜索一下,有个同伙已经写了一个贴在上面了.

第三个字段便是等效系统用户名,实际上便是赋与一个 cvs 用户一个等效的系统用户的权限,看下面的例子你就明白它的功能了.

readers:有 cvs 读权限的用户列表文件.便是一个一维列表.在这个文件中的用户对 cvs只有读权限.

writers:有 cvs 写权限的用户的列表文件.和 readers 一样,是一个一维列表.在这个文件中的用户对 cvs 有写权限.

上面三个文件在缺省安装的时刻可能都不存在,必要我们自己创建,好吧,现在照样让我们用一个例子来教授教化吧.假设我们有下面几个用户必要应用 cvs:

laser, gumpwu, henry, betty, anonymous.

此中 laser 和 gumpwu 是系统用户,而 henry, betty, anonymous 我们都不想给系统用户权限,并且 betty 和 anonymous 都是只读用户,而且 anonymous 更是连口令都没有.那么好,我们先做一些筹备事情,先创建一个 cvspub 用户,这个用户的责任是代表所有非系统用户的 cvs 用户读写 cvs 仓库.

#adduser

...

然后编辑 /etc/group,令 cvspub 用户在 cvs 组里,同时把其它有系统用户权限的用户加到 cvs 组里.(见上文)

然后编辑 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 了.这里面的道理和阐明我想就不多说了,着实很简单,和系统治理用户的观点是一样的.

现在办事器和客户端都设置好了,那么怎么用呢,我在这里写一个最简单的(预计也是最常用的)敕令先容:

首先,建立一个新的CVS项目,一样平常我们都已经有一些项目文件了,这样我们可以用下面步骤天生一个新的CVS项目:

进入到你的已有项目的目录,比如叫 cvstest:

$cdcvstest

运行敕令:

$cvs import -m "this is a cvstest project" cvstestv_0_0_1start

阐明:import 是cvs的敕令之一,表示向cvs仓库输入项目文件.

-m参数后面的字串是描述文本,随便写些故意义的器械,假如不加 -m 参

数,那么cvs会自动运行一个编辑器(一样平常是vi,然则可以经由过程改动情况变量

EDITOR来改成你爱好用的编辑器.)让你输入信息,

cvstest 是项目名称(实际上是仓库名,在CVS办事器上会存储在以这个名字

命名的仓库里.)

v_0_0_1是这个分支的总标记.没啥用(或谓不常用.)

start 是每次 import 标识文件的输入层次的标记,没啥用.这样我们就建立了一个CVS仓库了,然后,我们可以把这个测试项目的文件删除.试验一下若何从仓库获取文件.这里我假设上面的所有客户端事情你都已经做过了.

运行下面的敕令:

$cvs checkout cvstest从仓库中检索出cvstest项目的源文件.

假如你已经做过一次checkout了,那么不必要从新checkout,只必要进入cvstest项目的目录,更新一把就行了:

$cd cvstest

$cvs update一下即可.又或者你不想直接更新,只是想看看有没有更新的器械,那么:

$cvs status这时后会打印出一长串状态申报(你可能必要用类似less这样的敕令分页显示,或者定向到一个输出文件里逐步看.),对项目中的每个文件有一份状态申报,类似这样:

===================================================================

File: foo.cStatus: Up-to-date

Working revision:1.1.1.1 'Some Date'

Repository revision: 1.2/home/cvsroot/cvstest/foo.c,v

Sticky Tag:(none)

Sticky Date:(none)

Sticky Options:(none)

这里最紧张的便是 Status 栏,这里统共可能有四种状态:

Up-to-date:注解你要到的文件是最新的.

Locally Modified:注解你曾经改动过该文件,但还没有提交,你的版本比仓库里的新.

Needing Patch:注解有个哥们已经改动过该文件并且已经提交了!你的版本比仓库里的旧.

Needs Merge:注解你曾经改动过该文件,然则偏偏有个不知趣的也改动了这个文件,而且还提交给仓库了!

假如你只是想维持软件的同步的话(象我),那么上面的器械就足够用了.可是假如多人协作开拓项目的话,可就不是了这么简单了.当你参加项目,掩护文件时,就必要更多敕令,比如说你我都是某 nasdaq 项目的开拓职员:

1,你对某个文件做了改动,比如说改了ceo.c,加了一行法度榜样:printf("where can I find VC to cheat!");

改完之后你要把改动提交给仓库,用敕令:

$cvs commit -m "add a complain" ceo.c

或者便是:

$cvs commit -m "worry about money"

让cvs帮你反省哪个文件必要提交.

2,当我开始干活的时刻,可能我先:

$cvs status

一把,这时刻我会看到:

==================================================================

File: ceo.cStatus: Needing Patch

Working revision:1.1.1.1 'Some Date'

Repository revision: 1.2/home/cvsroot/nastaq/ceo.c,v

Sticky Tag:(none)

Sticky Date:(none)

Sticky Options:(none)

于是我知道有人改了ceo.c,于是我就:

$cvs update ceo.c

或者干脆:

$cvs update

把ceo.c这个文件更新为最新版本,然后再干活.然后提交.

假如是日你改动了coo.c,加了一行 puts("how about another kind of bragging?");

并且提交了,然则这时刻我已经 $cvs status 过了,便是说我不知道你的改动.

而我加了一行printf("You must shamelessly and seems knowingness to act as a coo");

并且傻乎乎地提交:

$cvs commit coo.c

这时刻,CVS会奉告我

cvs commit: Examing .

cvs server: Up-to-date check failed for 'coo.c'

cvs [server aborted]: correct above error first!

于是我知道有个狗屎在我改动文件确当口做了提交,于是我

$cvs update

这时cvs会申报:

RCS file: /home/cvsroot/nasdaq/coo.c,v

retrieving revision 1.1.1.1

retrieving revision 1.2

Merging differences between 1.1.1.1 and 1.2 into coo.c

rcsmerge: warning: conflicts during merge

cvs update: conflicts found in coo.c

C coo.c

奉告你coo.c有版本冲突,于是我编辑coo.c,这时一样平常文件里看起来象这样:

...

printf("You must shamelessly and seems knowingness to act as a coo");

>>>>>> 1.2

...

于是我把上面改成:

printf("You must shamelessly and seems knowingness to act as a coo");

puts("how about another kind of bragging?");

然后

$cvs commit -m "merged" coo.c

于是下回你再更新的时刻就有新的补钉要打...如斯来去,直到完成所有改动.

不过这里有一些要留意的地便利是删除法度榜样,假如你删掉落一行对你可能没有用的法度榜样

puts("to be honest"); 而我不想删除(由于我有用),而我不知情地直接:

$cvs update

了,那么我的这行法度榜样也垮台了,以是这里我们要留意所有开拓职员的和谐,切切不要乱删器械,大年夜不了用

#if0

#endif

宏定义对括起来.其实要删器械,那最好先标记一个版本:

$cvs tag v_0_0_1

然后你可以宣布并删除你自己的事情目录里这个版本的文件(留意:不是删除仓库里的.):

$cvs release -d nasdaq

然后你再天生一个新分支:

$cvs rtag -b -r v_0_0_1 v_0_0_1_1 nasdaq

然后再建立v_0_0_1_1的分支

$cvs checkout -r v_0_0_1_1 nasdaq

编辑并改动这个分支的文件,这样的做法对照好.

不过要留意的是,新标记和新分支的建立最好由项目的治理职员认真,否则每小我都做一个分支,那么仓库就太乱了.是以,对照的开拓职员之间的直接沟通是不能轻忽的.一样平常来说,在互联网上的标准模式是有一个治理员(可能自己并不写法度榜样),有一个邮递列表,大年夜家都在邮递列表上交流见地和做各类决议.当形成决议之后,治理员做一个新版本的标记.以此轮回.

还有一些敕令,比如要增添一个文件 garbage_china_concept_stocks_list:

$cvs add garbage_china_concept_stocks_list

然后还要:

$cvs commitgarbage_china_concert_stocks_list

看起来有点象数据库里的事务?切实着实是这样.CVS掩护着一个本地的参考文件(在CVS/Entries里),这样提交的时刻就可以一次地把所有改变放到办事器端,这样也更安然.同样,假如想删除文件 bankrupted_web_site:

$rm bankrupted_web_site

$cvs remove bankrupted_web_site

$cvs commit bankrupted_web_site

3,一些小技术:

$Header$ 标记:把这个标记放在文件的任何地方都邑被 cvs 调换成着末改动的 cvs 用户名,该文件当前版本号,着末改动光阴,该文件的 cvs 仓库路径,看起来象下面这个样子:

// $Header: /home/cvsroot/simhost/simhost.cpp,v 1.2 2001/04/20 08:26:10 jqliu Exp $

一样平常我们把它放在开首,这样对法度榜样员改动文件异常便利,很多时刻你只要看一眼开首就知道文件是否最新.

$Id$标记:把这个标记放在文件的任何地方都邑被 cvs 调换成着末改动的 cvs 用户名,该文件当前版本号,着末改动光阴,该文件的 cvs 仓库路径,看起来象下面这个样子:

$Id: simhost.cpp,v 1.3 2001/04/24 02:27:36 simhost Exp $

好了,上面所有的器械,预计便是我们用cvs时80%环境下用的敕令和内容,包括文件的更新,提交,冲突的办理,分支的派生,增删文件等.实际上cvs的功能之强大年夜,远远越过我在这里描述的内容,我这个"速成"也就管不了太多了,盼望跟着光阴的推移,我们能够加倍有效地应用CVS.也盼望大年夜家能够赓续弥补这篇文章,着末能够成为手册,而不仅仅是速成.当然,还要更多地参考其余文档.

您可能还会对下面的文章感兴趣: