最近项目使用cvs管理,研究了一段时间,参考了几个文档,总结如下
CVS完全手册 ========================================================================== He Wehzhu, kerlion@netease.com, created at 2003-11-5 updated at 2003-11-12 版权声明:可以任意转载,转载时请务必标明原始出处和作者信息 ==========================================================================
内容 概述 CVS环境设置 登录CVS服务器: cvs命令格式 CVS的日常使用 其他常用命令 CVS宏/keyword CVS分支管理 CVS服务器的安装和配置 Watchers WinCVS的安装和配置 CVSWEB的安装
概述 ==================================
CVS是一个并行版本控制系统,它采用C/S模式,它的复杂度和功能性属于中等,是当今最流行的版本控制系统。它有两个基本的特点: *保存修改记录:保存了所有文件的修改历史,并可以建立分支 *协作与并行:cvs不推荐使用lock-modify-unlock的串行的工作模式,而采用多人可以并行地修改同一个文件,而在提交时merge conflict;它更适合于大型的工作团体。 使用CVS的好处: *文件集中管理,大家都可以方便的看到所有人员的最新文件,规范化了文件的管理 *可以查看以前任何的一个版本或修改历史 *可以同时维护多个版本和分支
CVS环境设置 ==================================
先不要管CVS服务器的配置,我们先假设已经有一台配置好的服务器,要访问CVS,必需先设置环境变量CVSROOT CVSROOT=:pserver:user@server#port:/path/to/cvsroot
*pserver是访问方式,口令认证的意思,这是最常用的方式,其他还有gserver,kserver,ext *user是CVS服务器的用户名, *server是CVS服务器的名称或者IP地址 */path/to/cvsroot是你的CVS服务器的CVSROOT目录,根据你的CVS服务器设置做修改或者询问管理员 你可以把设置放到你的shell的profile里(.bash_profile,.profile等)这样就不用每次敲一长串命令了
高级功能:现在比较流行是使用ssh来加密口令和数据流 CVSROOT=:ext:user@server#port:/path/to/cvsroot CVS_RSH=ssh hints: 实际上没有CVSROOT也可以,你可以每次用cvs -d :pserver:user@server#port:/path/to/cvsroot来访问,而且它将忽略CVSROOT环境变量 ,也许你会笑我只有疯子才这么用,不过,cvs可以把每次使用的命令参数放到一个文件中,所以在~/.cvsrc中加入 cvs -d :pserver:user@server#port:/path/to/cvsroot 即可,它最大的好处是修改了立刻生效,而且它的优先级高于CVSROOT环境变量,到时候不要傻乎乎地来问我,我的环境变量真么不起作用了。
登录CVS服务器: ================================== $cvs login,这时候cvs会问你口令,请把你在CVS服务器上的口令敲进去 如果没有任何错误信息,恭喜你,成功了! 成功登录后将建立一个~/.cvspass文件,保存你的口令,以后就不用输入口令了.
cvs命令格式 ================================== cvs [global_opts] command [command_opts] [command_args] Global options 属于左边cvs的,是全局的 command_opts 属于左边command的,是局部的 cvs --help-commands查看命令列表 cvs -H command/cvs -help command 查看该命令的选项 hints:如果你每次使用一些命令都带同样的参数的话,可以把它们放到~/.cvsrc文件中去 update -c diff -c add -kb cvs -Q
cvs global-option comand comand-option arguments
CVS的日常使用 ================================== CVS使用流程 a checkout 尽当本地没有working copy时使用 b staus 检查服务器上是否有新版本 c update 如果有,则用update同步文件 d 做你自己的修改,并保证正确 e update 看是否有人修改了你的文件 f 如果有冲突,合并冲突 g commit 提交你的修改,如果因为又有人提交修改而失败,回到e步 h 回到b步
1 cvs checkout module_name ------------------------------------- module_name可以暂时理解为目录名,它会在本地但前目录下建立module_name目录,在把服务器上说有module_name目录下的文件copy到本地module_name目录下。 注意:第一次checkout后,就不是通过cvs checkout来同步文件了,而是要进入该目录下进行具体文件的版本同步(添加,修改,删除)操作。
2 cvs update filename ------------------------------------- 将文件同步到最新的版本:不指定文件名,cvs将同步所有子目录下的文件。 最好每天开始工作前或将自己的工作导入到CVS库里前都要做一次,并养成"先同步 后修改"的习惯,和Virvual SourceSafe不同,CVS里没有文件锁定的概念,所有的冲突是在commit之前解决,如果你修改过程中,有其他人修改并commit到了CVS库中,CVS会通知你文件冲突 <<<<<<< filename 你文件上的内容 ======= 服务器上文件的内容 >;>;>;>;>;>;>; latest revision number in the repository
由你确认冲突内容的取舍。也可以多人协商解决,修改完成后去掉文件中的冲突标志
conflict:多人修改同一文件的同一区域这就叫冲突,它必须由人来解决,CVS不处理冲突,它只是告诉你存才冲突
3 cvs commit -m "write some comments here" file_name ------------------------------------ 确认修改写入到CVS库里。 注意: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
4 查看状态 ------------------------------------ cvs status filename 状态报告,类似这样: File: foo.c Status: 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: 表明你曾经修改该文件,但是偏偏有个不识相的也修改了这个文件,而且还提交了!
5 查看修改历史和注释信息 ------------------------------------ cvs log file_name
其他常用命令 ================================== 1 添加文件和目录 ------------------------------------ cvs add new_file_name cvs add -kb new_file_name cvs add dir_name
CVS一般只处理文本文件,它会扩展keyword(宏)并转换行结束符 对于图片,Word文档等非纯文本的项目,需要使用cvs add -kb选项,否则有可能出现文件被破坏的情况 然后确认修改并注释 cvs ci -m "write some comments here" new_file_name
2 删除文件 ------------------------------------ 将某个源文件物理删除后 cvs remove file_name 然后确认修改并注释 cvs ci -m "write some comments here" file_name
注意:很多cvs命令都有缩写形式:commit=>;ci; update=>;up; checkout=>;co; remove=>;rm;
3.修改文件名 ------------------------------------ 移动文件:文件重命名 cvs里没有cvs move或cvs rename,因为这两个操作是先cvs remove old_file_name,然后cvs add new_file_name实现的。
4 目录结构同步 ------------------------------------ 如果在你checkout后,有人添加了新的文件或目录,你需要把他们取出来 cvs update -d
5 放弃本地的修改(undo) ------------------------------------ 如果修改来了本地文件,不想提交,想重新取新文件 cvs update -C filename 它会先把你的本地文件改名
建议:建议大家把checkout的文件缺省为readonly,把"cvs -r"添加到~/.cvsrc文件中 这样,你每次修改一个文件前,先cvs edit filename,提交后文件又变成readonly, 如果你想放弃本地的修改,则cvs unedit filename,它会undo,而且文件又变成readonly
6 恢复到旧版本 ------------------------------------ cvs update -j1.20 -j1.15 filenames 1.20时当前版本号,注意顺序不要反了,记住要commit,为了保证是但前版本号,最好先lock 注意:cvs update -r1.15 file.name,这里的-r不是版本号的意思,是给文件加了一个叫1.15的sticky tag 如果不小心已经加成STICK TAG的话:用cvs update -A 解决
7 文件比较 ------------------------------------ cvs diff -c filename cvs diff -c -r1.8 -r 1.5 filename
8 锁定与解锁文件 ------------------------------------ 为保证串行的修改文件,或修改二 cvs admin -l files cvs admin -u files
========================================================================== 如果你只是一般性的使用cvs,到此为止就足够了。一个系统20%的功能往往能够满足80%的需求,CVS也不例外,以下是CVS最常用的功能,可能用到的还不到它全部命令选项的10%,更多的功能请在实际应用过程中体会,学习过程中应该是用多少,学多少,用到了再学也不迟。 ==========================================================================
CVS宏/keyword ================================== CVS缺省会对文件进行keyword(宏)替换,在文件中加入这些关键字是个良好的工作习惯 $Id$ 关键字是用文件名、版本、时间、作者 及代码性质替换,如果使用-l选项取出,在Exp后 面会加上登录用户的名称。除了$Id$关键字,RCS还支持下面常用的关键字: $Log$ : 你所提供的修改日志信息。 $Author$ :存入该版本的作者。 $Locker$ : 该版本的加锁者 $State$ : 该版本的状态 Exp(试验版), Stabe(稳定版), Rel(发行版).缺省是Exp $Date$ : 该版本存入的时间,使用UTC时间格式。 $Revision$ : 该版本的版本号 $RCSfile$ : RCS文件名 $Source$ : RCS全路径名 $Name$ : 取回该版本的符号名 $Header$ : 相当于$ Source $$ Revision$$Date$$Author $$State$$Locker$的组合
Sticky Tag ================================== tag的作用是对多个连续变化的文件做一个快照来表示某一时刻的所有不停内部版本的文件,一般是项目到一定阶段,可以给所有文件统一指定一个阶段里程碑版本号,需要的时候可以一次导出这些版本不一的文件.标记的另外一个非常重要的作用是生成分支和合并分支. 1 cvs tag release_name module_name ------------------------------------ release_name要简洁而含义丰富,由字母开头,加字母,数字,下划线和连字号组成,特别是不能含“.” 2 cvs checkout -r release_name module_name ------------------------------------ 取出tag_name标志的文件 3 cvs update -A ------------------------------------ tag标识的文件是历史文件,不能修改,这样可在本地去除这个限制,让它和当前版本合并
CVS分支管理 ============================= CVS可以将历史划分成多个独立,并行和互不影响的分支,并去修改历史 1 标定里程碑 ------------------------------------ cvs tag release_1_0 prj_dir_name
2 开始一个新的里程碑: ------------------------------------ cvs commit -r 2 标记所有文件开始进入2.x的开发 注意:CVS里的revsion和软件包的发布版本可以没有直接的关系。但所有文件使用和发布版本一致的版本号比较有助于维护。
3 建立分支 ------------------------------------ 在开发项目的2.x版本的时候发现1.x有问题,但2.x又不敢用,则从先前标记的里程碑:release_1_0导出一个分支release_1_0_b2 cvs rtag -b -r release_1_0 release_1_0_bugfixes prj_dir_name -r修饰的是release_1_0,-b 修饰的是release_1_0_bugfixes,cvs的版本号将变为4位,以后每分一次支,版本号增加2位
4 分支并行开发 ------------------------------------ 一些人先在另外一个目录下导出release_1_0_bugfixes这个分支:解决1.0中的紧急问题, cvs checkout -r release_1_0_bugfixes 分支是可以修改的,并自动提交到分支上去 而其他人员仍旧在项目的主干分支2.x上开发
5 tag分支 ------------------------------------ 在release_1_0_bugfixes上修正错误后,标记一个1.0的错误修正版本号 cvs tag release_1_0_bugfixes_p1
6 合并分支 ------------------------------------ 如果2.0认为这些错误修改在2.0里也需要,也可以在2.0的开发目录下合并release_1_0_patch_1中的修改到当前代码中: cvs update -j release_1_0_bugfixes
7 再次合并分支 ------------------------------------ 如果又发现1.x新的bug,我在分支已经修改了,并标定了release_1_0_patch_2,我们同样希望把它合并到主干上来 cvs update -j release_1_0_bugfixes_p1 -j release_1_0_bugfixes 它的意思是把release_1_0_bugfixes_p1(tag)到release_1_0_bugfixes(分支)变化了的部分合并到当前文件(主干) 否则用6步的方法,则以前合并的内容会重新合并 注意:此时我们使用第5步的结果 教训:尽早频繁的tag,但同时不能导致tag泛滥,tag在不同的分支里可以同名
8 锁定分支 ------------------------------------ cvs admin -l r_0_2 锁定r_0_2分支 cvs admin -l 锁定主分支
9 设置缺省分支 ------------------------------------ cvs admin -b r_0_2 设定r_0_2为缺省分支 cvs admin -b 设定主分支
10 删除历史记录 如果历史文件过多,或确定有几个阶段的稳定版本,我们可以删除一些历史文件,以保证cvs的性能 cvs admin -o rev1:rev2 filename 删除rev1到rev2的版本,含这两个版本 cvs admin -o rev1::rev2 filename 删除rev1到rev2的版本,不含这两个版本 如果省略rev1,表示删除本分支rev2之前的所有版本 如果省略rev2,表示删除本分支rev1之后的所有版本 cvs admin -o rev filename 删除rev这个版本的文件 注意:有tag的版本不能被删除,所以tag很重要,而且只能删单个文件
CVS服务器的安装和配置 ============================= 1 下载源码 ------------------------------------ 可从很多地方下载cvs,也可从官方ftp://ftp.gnu.org/gnu/cvs/下载
2 安装,同很多源码安装一样 ------------------------------------ gunzip cvs-1.10.6.tar.gz tar xvf cvs-1.10.6.tar cd cvs-1.10.6 ./configure make make install
3 包的安装,如果找到具体操作系统的安装包,则见此操作系统的使用说明,比如linux为 ------------------------------------ rpm -ivh cvs-1.10.8-3.i386.rpm即可
4 建立Repository ------------------------------------ groupadd cvs(要访问cvs的用户加入此组) useradd cvsroot mkdir /home/cvsroot cvs -d /home/cvsroot init chown -R cvsroot.cvs /home/cvsroot chmod -R ug+rwx /homecvsroot
5 配置/etc/services文件 ------------------------------------ 添加cvspserver,如果有就不要加了 cvspserver 2401/tcp # cvs client/server operations cvspserver 2401/udp # cvs client/server operations
6 配置inetd ------------------------------------ 编辑/etc/inetd.conf,加入 cvspserver stream tcp nowait root /usr/bin/cvs cvs --allow-root=/home/cvsroot pserver 如果使用tcpwrappers cvspserver stream tcp nowait root /usr/sbin/tcpd /usr/bin/cvs --allow-root=/usr/local/newrepos pserver 如果使用xinetd,编辑/etc/xinetd.d/cvspserver service cvspserver { disable = no socket_type = stream wait = no user = root env = HOME= server = /usr/bin/cvs server_args = -f --allow-root=/home/cvsroot pserver } pserver表示是口令认证,如果要用ssh方式则应该是server --allow-root是Repository的目录,可以有多个此选项来建立多个Repository
7 验证配置成功 cvs login看时候能成功登录,有几个可能失败的地方 用户是否属于cvs组和目录权限 inetd是否正常配置和启动,--allow-root是否写对 8 导入项目 把你的所有项目文件放入prj_dir cd prj_dir cvs import -m "this is a cvstest project" prj_dir v_0_0_1 start v_0_0_1是这个分支的总标记.没啥用(或曰不常用) start 是每次 import 标识文件的输入层次的标记,没啥用。
Watchers ============================= cvs提供了watch的功能,来帮助大家了解谁在干什么,谁在对文件做什么操作,它发email通知,以协调大家的工作。 1 开启watch功能 在CVSROOT/notify文件中加入下面行 ALL mail %s -s "CVS notification" 2 设定外部email地址 缺省是把通知信息发给本机的email,要发给别的地址,在CVSROOT/users加入如下内容 hwz:kerlion@netease.com 3 watch文件的修改 cvs watch add filename cvs watch remove filename 4 watch文件的修改 watch功能是个大家协调的功能,大家必须按一个统一的工作流程来做,如果不cvs edit,cvs没有办法通知修改情况 cvs edit filename 修改文件 cvs unedit filename 5 提醒大家使用watch功能 cvs没有强制使用watch的功能,只有这个功能在用户提交完后自动把文件变为只读的,再使用cvs edit filename就可以修改它了 cvs watch on 6 查看那人人再watch cvs watchers
WinCVS的安装和配置 ============================= 1、WinCVS简介: WinCVS是CVS的一个客户端软件,它运行在Windows上,用来在Windows上登录CVS服务器,然后进行一些CVS相关的操作与管理。由于当前很多的企业内部都采用Linux/Unix做服务器,而用Windows做客户端,所以,WinCVS与CVS服务器配合使用将组成最强有力的版本控制与管理的系统之一。 2、WinCVS的下载与安装; 最新的WinCVS可以从http://sourceforge.net/project/showfiles.php?group_id=10072地址下载到,也可以在http://sourceforge.net/project 上下载到最新的或其它版本的WinCVS。 下载到相应的版本后根据向导进行安装,已经要使用CVS的用户,安装这个WinCVS应该没什么问题吧! 3、配置WinCVS: a、Admin->;Preferences…/general CVSROOT 按cvsroot格式填写 Authentication:用来配置cvs服务器的认证方式一般只要选择默认的pserver方式就可以 要注意的是必须与cvs服务器配置时所指定的认证方式一致 如果要用ssh server,确认在windows中安装了openssl,openssh a、Admin->;Preferences…/Globals 此项的配置主要是要注意这几选项: Checkout read-only:默认是选中的,建议不要修改,只是修改文件前需要先edit selection,提交后又自动变为只读 这样有两个好处: 一个是可以通过unedit selection来undo你做的修改 二是可以符合watch功能的使用规范 Prune empty directories: 不要选上,否则,会自动删除空目录; 4、登录服务器: 选择Admin->;login,将出现如下对话框要求用户输入登录口令 wincvs中命令的exit code 0表示正确执行,否则是失败,一般成功显示为 *****CVS exited normally with code 0***** 5、winCVS的使用都有菜单,大家熟悉cvs的使用的话,用起来是很容易的,我就不多说了
CVSWEB的安装 ============================= CVSWEB就是CVS的WEB界面,可以大大提高程序员定位修改的效率: 使用的样例可以看:http://www.freebsd.org/cgi/cvsweb.cgi
CVSWEB的下载:CVSWEB从最初的版本已经演化出很多功能界面更丰富的版本,这个是个人感觉觉得安装设置比较方便的: http://www.spaghetti-code.de/software/linux/cvsweb/
1 下载解包: tar zxf cvsweb.tgz
2 把配置文件cvsweb.conf复制到apache的配置目录下 cp cvsweb.conf /path/to/apache/conf 转到/path/to/apache/conf下并修改cvsweb.conf: 修改CVSROOT路径设置: %CVSROOT = ( 'Development' =>; '/path/to/cvsroot/dev', #<==修改指向本地的CVSROOT 'test' =>; '/path/to/cvsroot/test', #<==修改指向本地的CVSROOT ); 如果有多个cvsroot,这定缺省的cvsroot $cvstreedefault = 'test';
3 其它个性化设置 cvsweb.conf还有许多其它个性化设置,常见的有这些变量: $logo 图标设置 $defaulttitle 标题设施 $address 管理员email地址设置 $long_intro 介绍文字 $short_instruction 说明文字
4 把文件cvsweb.cgi复制到apache的cgi目录 cp cvsweb.cgi /path/to/apache/cgi-bin 转到/path/to/apache/cgi-bin修改cvsweb.cgi 修改cvsweb.cgi让CGI找到配置文件: $config = $ENV{'CVSWEB_CONFIG'} || '/path/to/apache/conf/cvsweb.conf';
5 中文支持 让cvsweb正确显示中文,找到sub html_header($)函数, 然后在<html>;和<title>;之间插入一行,修改如下 <html>; <meta http-equiv="Content-Type" content="text/html; charset=gb2312">; <title>;$title</title>; 6 复制所有的gif,png文件到apache的icons目录 7 增加访问控制 CVSWEB可不能随便开放给所有用户,因此需要使用WEB用户认证: 先生成 passwd: /path/to/apache/bin/htpasswd -c cvsweb.passwd user
修改httpd.conf: 增加 <Directory "/path/to/apache/cgi-bin/cvsweb/">; AuthName "CVS Authorization" AuthType Basic AuthUserFile /path/to/cvsweb.passwd require valid-user </Directory>;
========================================================================== 参考文档: CVS的常用命令速查手册,车东,chedong@bigfoot.com CVS服务器与WinCVS的配置与使用,吴炎溪,Yanxi-Wu@21cn.com CVS速成班,作者不祥 cvs book,Karl Fogel,kfogel@red-bean.com ==========================================================================
另: 用了这么长的时间,我在谈一下模块管理问题, 在CVS中模块,项目,目录的概念有点混乱,得靠自己去理解。 一个CVS服务器可由多个cvsroot,每个cvsroot可有多个项目,每个项目可有多个模块.通过摸索我觉得一下方式比较好。 每个cvsroot只建立一个项目,多个项目通过多个cvsroot实现。
如果我们直接在cvsroot下建立各种模块,好像没有办法对这些模块打上统一得tag(至少我没有找到,知道的请告诉我);这在产品发布的时候很麻烦。如果我们只建立一个模块,真正的模块当作子目录放在其中,我们又没有办法直接checkout一个模块,导致路径很深,同时没有办法在模块上建立分支,必须在全项目范围内建立分支。
比较好的方法是: 在cvsroot下只建立一个modules(实际上我们认为是project),真正的modules放在其下;然后建立虚modules.方法是 在服务器上的prj_name/CVSROOT/中编辑文件modules m1 prj_name/m1 m2 prj_name/m2 m3 prj_name/m3 m3a prj_name/m3/m3a m3b prj_name/m3/m3b m3c prj_name/m3/m3c 这样我们就可在proect或modules的级别上打tag和建立分支
还有一个好处是,我们可以用下面的命令查看有那些模块 cvs co -c
| |