cvs ( Concurrent Version System )是一个版本控制系统,什么是版本控制系统呢?简单的说,它可以记录程序代码修改的过程,有一个完整的历史记录( history )。辟如说,当你在修改程序代码的时候, 不小心写出了一个 bug,但是你可能很久以后才发现多出了这个 bug, 这个时候,cvs 就能很有效的帮助你找出到底是在哪一次的修改中,出现了这个 bug。
    也许你会说, 那我每次都把程序保存起来, 用tar 做好备份不就行了,当然, 你可以这样做, 但是这太浪费空间了! cvs 在版本更改间, 只储存不同的部分, 这样就可以省下很多空间。
在另一个场合里, 更能显示出 cvs 的好处 ,比如多人一起开发软件的时候。 cvs支持远程访问, 用户可以对他要修改的文件加上正在编辑的标志, 让别人知道他要修改这个文件了。 当然, 一个较大的开发队伍,一般还会需要一个 mailing list 用来沟通。毕竟cvs 只是一个管理程序代码的工具, 他并不扮演沟通的角色。  
cvs的同类软件还有rcs和sccs。RCS ( Revision Control System ) 可以从FSF获得。SCCS ( Source Code Control System ) 由AT&T在SystemV中引入,现在已经被加入X/Open标准( Unix 98? )。比起这些软件,CVS的要优秀得多,特别是在支持多人远程开发方面。由于CVS出现较新,所以使用上反而没有它们普及。当然,如果您熟悉rcs,您会发现学习cvs非常容易。名词 
repository: 意为仓库。在 cvs 里, 它就是你真正存放各历史版本的地方。
   pserver: cvs 远程服务器,cvs 有两种工作模式, 一种是 local, 一种是 remote。 一般通过inetd启动pserver。
   CVSROOT: 当使用 cvs 的时候, 要设定 CVSROOT这个环境变量, 或是用 -d 选项来指定该参数,该参数指明你的仓库放在哪里。本地( local )cvs 
    首先, 确定一个 cvsroot,比如: 
export CVSROOT="/home/joe/cvsroot/" 
    建立该目录:
mkdir /home/joe/cvsroot
接着,运行cvs init :
    cvs init 
    cvs init 会帮你把 cvsroot 初始化。接着, 建立一个要放文件的目录 ( 相当于一个Project ): 
    mkdir /home/joe/cvsroot/cvsdoc   
cd /home/joe/work 
    cvs checkout cvsdoc( 或者简写为: cvs co cvsdoc )
   你会看到下面的信息: 
cvs checkout: Updating cvsdoc 
   cvs checkout 会把当前最新的版本拷贝到你的当前目录下。 
   记住, 不要自己建立 /home/joe/work/cvsdoc, 该目录下还会有一些用于管理的 cvs 相关的信息。 
接着, 进入 cvsdoc 目录, 编辑 cvs.doc 这个文件档案,输入一些信息。
然后,运行:
    cvs add cvs.txt 
    cvs commit -m "Initial revision." 
    cvs add 就会把 cvs.txt 加入 cvs 维护的文件列表中去。
   cvs commit 检查当前目录下所有的在文件列表中的文件,并把对他们的改动加入到仓库中。-m 表示这次 commit 的 message,一般说明此次修改的相关信息。
    现在修改一下 cvs.txt,并且,在文件档案的最上面加上 $Id$ 的字样。
   改完之后, 再 commit 一次:
cvs commit -m "Adding new stuff." 现在看看我们所做的修改:
cvs log cvs.txt 
可以看到:
RCS file: /home/joe/cvsroot/cvsdoc/cvs.txt,v
Working file: cvs.txt
head: 1.2
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 2;     selected revisions: 2
description:
----------------------------
revision 1.2
date: 2000/09/11 11:55:06;  author: joe;  state: Exp;  lines: +2 -0
i
----------------------------
revision 1.1
date: 2000/09/11 11:52:32;  author: joe;  state: Exp;
initial version
==================================================================
    你会看到每次修改加进去的 message。这对开发者,特别是一个大的项目的开发者,其帮助是不言而喻的。
cvs diff -r 1.1 -r 1.2 cvs.txt 
可以看到:
Index: cvs.txt
================================================================== RCS file: /home/joe/cvsroot/cvsdoc/cvs.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -r1.1 -r1.2
0a1
> $Id: cvs.txt,v 1.2 2000/09/11 11:55:06 joe Exp $
1a3
> hehe,sencond time edit it!    这样会显示 1.1 和 1.2 版的 diff, 原本有 1.1 版的人, 只需要用这个 patch 就可以了升级到1.2了! 再编辑 cvs.txt, 可以发现最上面的 Id 变长了? 加了一代串文字:
$Id: cvs.txt,v 1.2 2000/09/11 11:55:06 joe Exp $ 
   这显示这个版本的一些相关信息。 远程( remote )cvs 
如果我们要做一个比较大的项目,上面讲的本地cvs服务就太简单了,我们要让众多的人可以远程开发程序! 比如我们要用cvs组织起我们的minigui项目。
    检查 /etc/services 有没有这两行,没有请加入:cvspserver      2401/tcp   #CVS network server 
    cvspserver      2401/udp   #CVS network server 在 /etc/inetd.conf 加入:
cvspserver stream tcp nowait root /usr/local/bin/cvs cvs --allow-root=/home/minigui pserver
mkdir /home/minigui
要是该设置生效,请重启inetd。
   添加用户anoncvs, 这是要给匿名cvs 用户使用的帐号,其组为nogroup。 
   新加一个名为 minigui的 group。 
   添加参与 minigui开发的用户的帐号, 当然, 把他们的 group 设为 minigui。    cvs -d /home/minigui init cd /root/minigui, 这是原来已经存在的版本, 现在我们要把它的东西放进 cvs 仓库里: 
比如,我们把minigui的库minigui03放到仓库中:cd minigui03;cvs import –m “the lib” minigui03 joe start会看到cvs把一个个文件放到仓库中。
cvs import 的语法为: cvs import -m "log msg" projname vendortag releasetagvendortag 和releasetag 一般不需要关心,我们这里使用一个用户名和一个start 标志。
我们把其它相关的project也放到cvs仓库中:cd miniguiapps03 ; cvs import –m “the apps” miniguiapps03 joe start
cd miniguiexec03 ; cvs import –m “the demos” miniguiexec03 joe start 这样,我们就把minigui的一个cvs服务器建立好了。
注意, 一个 user 要远程访问某些project, 他必须拥有适当的权限。比如,minigui03这个目录应该属于组minigui,且组可写。才能使minigui组里的用户可以远程参与minigui库的开发。   现在试试看从远程访问 cvs 服务器。
   首先, 在你的机器上建立一个工作目录, 譬如是 /home/joe/work cd /home/joe/work 
cvs -d :pserver:[email protected]:/home/minigui login
cvs -d :pserver:[email protected]:/home/minigui co minigui03
cvs -d :pserver:[email protected]:/home/minigui co miniguiapps03
cvs -d :pserver:[email protected]:/home/minigui co miniguiexec03
cvs -d :pserver:[email protected]:/home/minigui logout
当你敲入login行时,系统会提示你输入password, 打进去。 
    www.minigui.org是cvs服务器所在的机器。 
该指定被执行后,该 cvsroot 
(:pserver:[email protected]:/home/minigui) 和加密后的密码会被存在 ~/.cvspass 里。  底下几行取出各个project。最后logout。 cd minigui03 做了一些修改后,可以commit出去:cvs commit -m "little change" 上面是一般开发者的登陆方法,对于匿名cvs, 可以让其不需要输入口令即可登陆,但是不能让其commint。这需要:
1. 将要开放的project设为全局可读写,因为cvs服务器在操作时要在相应目录下设置读写琐(即需要创建一些临时文件),所以即使是check out 操作,也需要目录可写。
2. 为了让匿名用户只有check out权限,可以在CVSROOT目录下建立一个readers文件,其中每一行是一个用户,这些用户只具有只读权限。比如:
anonymous
anoncvs
guest
jbrowse
3.  利用passwd文件,使匿名用户不能用其它方式登陆。典型为:
在文件CVSROOT/passwd 中:
anoncvs:XR4EZcEs0szik
在文件/etc/passwd 中为:
anoncvs:!:1729:105:Anonymous CVS User:/home/minigui:/bin/false
CVSROOT/passwd文件是cvs提供的一个专用于存放cvs密码的文件。它的典型格式为:
joe:XR4EZcEs0szik:jane
表示cvs用户joe其实是内部用户jane,其cvs密码加密后被存放在第二个字段,这样就将cvs服务与系统的其它部分分离开来,大大地提高了系统的安全性。
上面介绍的是使用需要严格的安全认证的pserver服务器,如果您在局域网内开发程序,则可以使用rsh或者ssh,设置非常简单,服务器端只要开放着rsh或ssh服务器,客户端设置两个环境变量:CVS_RSH与CVSROOT,可以将它们的设置写入预处理脚本,比如使用ssh连接:$export CVS_RSH="ssh"
$export CVSROOT=":ext:[email protected]:/home/minigui"$ cvs co miniguiexec03
[email protected]'s password: 输入密码,就可以得到一份miniguiexec03的拷贝了。
总结
以上只是一个简介,cvs还有很多高级功能,如果您需要更详细的信息,请看cvs 的info或者到gnu上下载html版本的manual。

解决方案 »

  1.   

    CVS是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。工作模式如下:CVS服务器(文件版本库) 
    开发人员入门可以主要挑选2,6看就可以了,CVS的管理员则更需要懂的更多一些,最后还简单介绍了一些Windows下的cvs客户端使用,远程用户认证的选择,及与BUG跟踪系统等开发环境的集成问题。CVS环境初始化:CVS环境的搭建 管理员
    CVS的日常使用:日常开发中最常用的CVS命令, 开发人员 管理员
    CVS的分支开发:项目按照不同进度和目标并发进行 管理员
    CVS的用户认证:通过SSH的远程用户认证,安全,简单 管理员
    CVSWEB:CVS的WEB访问界面大大提高代码版本比较的效率 管理员
    CVS TAG:将$Header$加入代码注释中,方便开发过程的跟踪 开发人员
    CVS vs VSS: CVS和Virsual SourceSafe的比较 开发人员 管理员
    WinCVS: 通过SSH认证的WinCVS认证设置
    基于CVSTrac的小组开发环境搭建:通过CVSTrac实现web界面的CVS用户管理及集成的BUG跟踪和WIKI交流。
    一个系统20%的功能往往能够满足80%的需求,CVS也不例外,以下是CVS最常用的功能,可能还不到它全部命令选项的20%,更多的功能在实际应用过程中体会,你想用多少就学多少,不时回头看看经常有意外的收获。CVS环境初始化
    环境设置:指定CVS库的路径CVSROOT
    tcsh
    setenv CVSROOT /path/to/cvsroot
    bash
    CVSROOT=/path/to/cvsroot export CVSROOT后面还提到远程CVS服务器的设置:
    CVSROOT=:ext:[email protected]#port:/path/to/cvsroot CVS_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