CVS基本使用方法
- 格式:doc
- 大小:62.00 KB
- 文档页数:9
CVS 使用手册
(仅供内部交流使用)
一、 基本概念
CVS是一个可以多人协同工作的文件版本管理工具,常用于源代码的管理,也可以用于其他基于文本结构的文件的历史版本管理。
CVS是基于文件进行管理,并不保存目录的变更信息。保存每一个文件的每一次修改的信息,能够方便的查找到每一个文件的不同时刻的版本的内容。可以方便查找旧有版本进行比较或者回退。通过TAG记录版本的统一基准。通过分支支持多版本的开发与合并。对第三方代码的跟踪提供了支持。
CVS使用中心源代码库和个人工作空间的方式。使用CVS进行管理的项目有一个中心的源代码库(Repository),然后开发人员checkout到本地的个人工作空间中进行修改,修改完毕之后将新的版本commit到中心源代码库中,其他开发人员可以将这个新的版本update到他们本地的个人工作空间中。
CVS在多人协同上没有采用加锁机制(lock-modify-unlock),而是使用冲突合并机制(copy-modify-merge)。所有人可以同时修改同一个文件,后提交的人需要将别人已提交的更新合并到本地,解决不同修改之间的冲突,再提交新版本。
CVS所管理的文件,每一个版本都有一个唯一的版本号,通常使用1.1、1.2的方式递增。而分支的版本号则增加两位,如1.3.1.4、1.3.1.5等。为了方便记忆,可以通过TAG的操作,为某一时刻的不同文件添加同一个版本名称。另外,可以通过某个特定的时间点的方式来指定所需的版本。
二、 代码修改
2.1. 准备工作
CVS可以通过本地路径、pserver、ssh tunnel的方式来访问,这里主要讨论pserver方式。
为了避免每次输入cvs命令都加 –d :pserver:user@host:/path 的参数,可以设置CVSROOT变量,这个设置可以写入 ~/.bashrc 或 ~/.bash_profile 中,在执行CVS其他命令前,要先执行一下cvs login命令:
$ export CVSROOT=:pserver:username@192.168.100.2:/cvsroot/proj
$ cvs login
(另外,CVS服务器建立提供服务前,首先要初始化,使用 $ cvs init 命令(略)。)
2.2. 创建新项目
通过CVS来管理项目时,首先要使用cvs import命令将原始版本放入CVS中。创建新项目时要注意下列事项:
(1) 在原始版本所在的目录里面执行import命令。import前先去掉一些可以从其他文件中生成的中间文件。
(2) import后要备份原始版本,然后checkout新版本,以后所有的修改都在checkout的版本上进行,import动作并不会把当前目录转换成checkout的版本。
(3) import后要将checkout的版本和原始版本做一下diff命令(exclude CVS目录),检查是否有不恰当ignore的内容。小心一些以点开头的隐藏文件。
(4) 检查是否有二进制文件被误作文本文件对待,使用cvs admin命令纠正。
$ pwd
/work/myproj
$ cvs import –m “why import this” myproj seals v_old_1_2_3
$ cd .. ; mv myproj myproj.ori
$ cvs checkout myproj
$ diff –r myproj.ori myproj | more
$ tar czvf myproj.ori.bak.xxxxxx.tar.gz myproj.ori ; rm –rf myproj.ori
$ cvs admin –kb mysub/mysubfile.dat
import命令的两个最后参数分别表示vendor和release_tag。一般vendor使用seals,release_tag使用init_xxxxxxxxxx即可。如果是使用第三方代码,则需要小心使用,并且使用readme.txt文件记录好每次import和merge信息,具体见【跟踪第三方源代码】一节。
import后的项目不能通过cvs命令删除,如果发现import出错,需要删除后重新import,则删除动作需要由管理员直接在代码库中进行删除。
2.3. 查看源代码
使用一个已经存在的CVS项目时,首先将其checkout到本地。根据Seals团队习惯,在CVS项目的根目录中,有PROG_VERSION.def文件存放项目的版本,有readme.txt文件存放介绍内容,有Changelog.txt文件存放版本的重大更新,习惯在Changelog.txt文件的开头写上此CVS项目所依赖到的其他项目。
$ cvs checkout myproj
$ cat PROG_VERSION.def ; cat Changelog.txt ; cat readme*
开发过程中,应该多执行一下update操作,及时获取其他开发者的更新,以减少可能存在的开发冲突。update的时候,文件名左边的字母的意思为:
“M”表示本地有修改未commit,
“P”“U”表示有其他人修改的新版本,已经更新到本地,
“C”本地有修改,并且与其他开发者者的改动有冲突。
update常用参数:
-d表示将新增加的目录也更新到本地(缺省是不更新);
-P表示删除本地的空目录。
-A 命令表示去掉粘着的tag(具体见【TAG和分支】一章)
$ cvs update –d –P
cvs update命令可以使用 –r 参数更新到指定TAG和分支上,然后这个TAG和分支会附在这些文件上(cvs status命令可以看到),后续的update将会保持这个TAG或分支不变,不会更新到最新代码,直到update时使用 –A 参数为止,参考【TAG和分支】一章。
使用cvs diff命令可以检查当前版本与CVS中的版本的差异,也可以比较指定两个版本之间的差异:
$ cvs diff –r 1.44 myfile.cpp
$ cvs diff –D “3 hours ago” myfile.cpp
$ cvs diff –r 1.42 –r 1.43 myfile.cpp
除了比较文件版本的差异,使用CVS还可以查看各个文件的具体修改日志,当前文件的状态,以及文件的各行的修改情况:
$ cvs log myfile.cpp
$ cvs status –v myfile.cpp
$ cvs annotate myfile.cpp > tmpfile.txt
另外还可以使用第三方工具可以生成统计信息和分析信息,方便查看。
2.4. 修改源代码
源代码修改时的一些注意事项:
(1) 修改过程中,多执行一下cvs update操作,以便尽早发现冲突并解决。
(2) commit的代码必须是可以编译通过的,而且最好不要有会影响其他模块运行的重大功能倒退,以免影响其他模块的开发。
(3) 在满足上述条件的同时,尽可能多commit,有阶段性成果就可以commit一下,以便其他开发人员尽早进行update,减少冲突。 (4) commit之前使用cvs update和cvs diff来检查一下需要提交的代码,commit之后使用cvs update来检查提交的结果。特别要注意检查是否有新增加的文件或者目录忘记使用cvs add添加到CVS中,这是非常容易遗漏的。
(5) commit的时候一定要写log信息。log信息应该简练,包含有效信息,同一任务的多个修改可以考虑使用同一个log信息,方便一些工具进行收集和汇总。
(6) CVS只是工具,不能代替团队的交流。团队开发过程中应该加强前期的讨论交流,减少后期的代码冲突合并。
$ cvs update –d -P
$ cvs diff –r 1.44 myfile.cpp
$ ./do_my_file_edit
$ rm nouse.h nouse.cpp
$ cvs remove nouse.h nouse.cpp (这两步可以合并成 cvs remove –f xxx)
$ cvs add newfile.cpp newfile.h
$ cvs diff
$ cvs update –d –P
$ cvs commit
一般要避免commit错误的代码,commit前最好先diff。如果需要将部分代码退回到某个版本,要加强沟通,讨论后再执行。主要有下列两种方法:(取回前一个版本,但不更改服务器中数据,需要commit。)
$ cvs –Q update –p –r 1.3 hello.c > hello.c
或:
$ cvs update –j 1.4 –j 1.3 hello.c
cvs中增加目录直接cvs add,不需要commit,但目录里面的文件不会自动添加,需要手动逐个add后再commit。如果目录层次比较多,除了逐层add目录再add文件外,也可以使用import命令(参考【跟踪第三方源代码】一节)。
$ cvs import –m “new dir” myproj/newdir seals v_init_newdir
删除文件要先删除本地文件,再执行cvs remove命令,或者直接cvs remove –f来操作。删除目录直接删除里面的文件即可,目录本身不需要删除,然后update使用-P参数可以去除空目录。
CVS不支持文件和目录的改名操作。可以考虑使用先remove再add的方法,一方面比较麻烦,另一方面log信息不能延续。所以文件和目录命名时要谨慎。
2.5. 跟踪第三方源代码
如果要使用到第三方源代码,可以通过多次import然后merge来进行。此时需要注意import时候的后两个参数(其实前一个是branch标记,后一个是tag标记),第一个参数要