CVS
常用命令
1.
CVS
简介
CVS
(Concurrent Versions
System)是一个版本控制系统。使用它,你可以记录下你的源文件的历史。例如:修改软件时可能会产生一些bug,而且可能过了很久你才会察觉到它们的存在。有了CVS,你可以很容易地恢复旧版本,并从中看出到底是哪个修改导致了这个bug
。有时这是很有用的。当然了,你可能把所有版本的所有文件都保存了下来。但这会浪费大量的磁盘空间。而CVS用一种聪明的办法来保存一个文件的所有版本——仅仅保存不同版本之间的区别——在一个文件里。如果你是项目开发组的一员,CVS也会帮助你。除非极为小心,成员之间很容易互相覆盖文件。一些编辑器,如GNU
Emacs,会保证同一时间内同一文件绝不会被两个人修改。不幸的是,如果有人用了另外的编辑器,这种保护就没用了。CVS用隔离开不同的开发者解决了这个问题。每个开发者在他自己的目录里工作,等每一个开发者都完成了他们自己的工作后,CVS会将它们合并到一起。CVS最初由Dick Grune在1986年12月以shell scripts的形式发布在comp.sources.unix的新闻组第6卷里。虽然当前的CVS中没什么代码来自于这些shell scripts,但许多CVS的冲突解决算法是从它们来的。1989年4月,Brian Berliner设计了CVS并编写了代码,之后Jeff Polk帮助Brian设计了CVS模块发行分支。
CVS
是一个C/S系统,多个开发人员通过一个中心版本控制系统来记录文件版本,从而达到保证文件同步的目的。工作模式如下:
CVS
服务器(文件版本库)
/ | \
(版本 同 步)
/ |
\
开发者1
开发者2 开发者3
2.
设置
CVS
客户端
如果不是在
CVS
服务器本地工作,则需要远程访问
CVS
服务器,这就需要对
CVS
客户端进行设置。
下面就讲讲如何远程访问
CVS
服务器。
首先要在
CVS
服务器上开设用户帐号,并加入
casic
组,这个帐号可以向
CVS
管理员申请开设。这里申请假设开设了帐号
ynding
。给帐号
ynding
设置环境变量
CVSROOT
的值为
/home/casic/cvsroot
,这样,在
CVS
本地机上帐号
ynding
就可以访问
CVS
库了。
在远程机器上也建立帐号
ynding
(当然也可以是其他帐号,开发时为了不混淆,取相同的帐号名为好),也给该
ynding
设置环境变量
CVSROOT
:
setenv CVSROOT
:pserver:ynding@192.168.0.148:/home/casic/cvsroot
或者
export
CVSROOT=:pserver:ynding@192.168.0.148:/home/casic/cvsroot
对环境变量的设置可在设置环境的文件里进行,这个请参照附录。
设置完环境变量并让它起作用以后,就可以远程访问
CVS
服务器了。
先要登录到
CVS
服务器上:
cvs login
会提示输入密码,输入帐号
ynding
在
CVS
服务器上的密码,就能登录成功了。以后的对
CVS
服务器的操作跟在
CVS
服务器本地操作一样。完事以后,记得使用命令
cvs logout
退出
CVS
服务器。
3.
常用命令预览
1)
cvs login
2)
cvs checkout / cvs co
3)
cvs update / cvs up
4)
cvs commit / cvs ci
5)
cvs admin
6)
cvs add
7)
cvs remove / cvs rm
8)
cvs log
9)
cvs history
10)
cvs status / cvs st
11)
cvs diff
12)
cvs export
13)
cvs logout
4.
常用命令解释
现在
CVS
源码库中有一个目录
pub
,专门用来让大家熟悉
cvs
命令,大家可以随意在这个目录下练习使用
cvs
命令。
1)
cvs login
当要远程访问
CVS
服务器时,首先需要登陆
CVS
服务器。在拥有
CVS
服务器帐号并设置好
CVS
客户端的情况下,可以使用该命令登录
CVS
服务器,执行该命令后会提示输入密码。
至于客户端怎么设置,请参考文档《
CVS
服务器管理》。
2)
cvs checkout / cvs co
该命令用来从
CVS
库中提取源文件。
提取源文件的时候,可以整个项目同时提取,或只提取项目中的一个子目录,或者就是单个的源文件。下面看提取的
3
种情况:
cvs co pub
cvs co
pub/testdir1
cvs co
pub/testdir1/test1.txt
这里我们把整个
pub
目录提取出来:
cvs co
pub
3)
cvs update / cvs up
将文件同步到最新版本。
同步有以下几种情况:
a)
后面不带文件名
将同步当前目录下的所有文件和子目录。
b)
后面跟一个或几个文件名
将只同步指定的文件。
c)
后面跟目录
将同步该目录下的所有文件和子目录。
下面再介绍一下后面只跟一个文件名的情况,其他情况类同:
1)
如果该文件的版本比库里的版本低,且该文件在提取之后在当前目录下没有被改动过,则该命令会将其更新到最新版本。
2)
如果版本比库里低,而且被改动过,使用该命令后将提示版本不一样,将合并两个不同版本到最新版本。这种情况很容易出现冲突,而且即使没有发现冲突合并成功,合并的结果也不一定是你想要的。所以我们不提倡在这种情况下提交文件,应该先检查一下文件的状态再作决定如何做,至于如何检查,下面会有描述。
3)
版本跟库里一样,且文件改动过,则该命令什么也不做,在提示中文件的前面加
M
标记,表示可以提交了。
4)
版本跟库里一样,而且没有改动,则该命令什么也不做,甚至没有任何提示。
4)
cvs commit / cvs ci
提交文件,确认修改写入
CVS
库里。
前面的
cvs update
命令并不能将修改写人
CVS
库了,在
cvs update
成功过后,在通过
cvs ci
命令将修改写入
CVS
库里。命令格式:
cvs ci –m “modify it to
demo this command” filename
其中
-m
后面是这次修改的注释,阐述修改的地方和原因,尽量能反映此次改动,为以后跟踪改动提供方面。如果不加
-m
,则会打开一个默认文本编辑器(通常是
vi
)让你编辑注释。
5)
cvs admin
常用来恢复错误操作。
具体使用将在其他地方有所阐述。例如,如果在提交文件的时候,或对某文件的某一个版本的注释不满意,决定修改它,可以运行命令:
cvs admin –m 1.2:”give a
new comment” filename
6)
cvs add
添加文件或目录。
添加文件的时候,将文件拷贝到当前目录下,运行命令:
cvs add
filename
为了添加成功,还必须使用
cvs ci
命令来确认添加:
cvs ci –m
“add a file for test” filename
如果要添加的是二进制文件,要以二进制的方式加入,否则可能会出现文件破坏的情况:
cvs add
–kb newfile.gif
cvs add
–kb readme.doc
添加目录的时候,只能添加空目录,目录下的文件还得进入该目录下继续添加,添加目录的时候不需要
cvs ci
确认,运行下列命令即可:
cvs add
dir
7)
cvs remove / cvs rm
删除文件。
运行命令:
cvs rm
filename
cvs ci –m “reason for
deleting this file” filename
在
cvs
里面不能删除一个目录,要删除一个目录,只要把它的里面的文件删除就行了。不过下次提取的时候删除的目录还会被提取出来,只不过是个空目录而已,这样比较麻烦,所以在
CVS
库里建立目录要非常谨慎。如果觉得这些空目录实在碍眼的话,可以使用命令:
cvs update –P
将空目录删除。或在提取的时候使用
-P
选项:
cvs co –P project_name
如果你想保留某个目录来存放文件,最好在该目录下存放一个文件,例如
.keepme
,这样,该目录就不会被
-P
选项删除了。
8)
cvs log
打印出文件的修改历史,从创建到现在。命令:
cvs log
filename
9)
cvs history
打印修改历史。命令:
cvs history
filename
10)
cvs status / cvs st
查询当前文件的状态,包括当前的版本号,还有库里的版本号。
运行命令:
cvs st
test1.txt
运行结果:
File: test1.txt Status: Up-to-date
Working revision: 1.3
Fri Aug 1 03:20:42
2003
Repository revision:
1.3
/home/casic/cvsroot/pub/testdir1/test1.txt,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
其中
Status
一栏为
Up-to-date
,表示当前文件和库里的一样。
状态还可能为以下几个:
Locally
Modified:
你修改了文件,并且还没有提交。
Locally
Added:
使用
cvs
add
命令添加了该文件,但没有完成提交。
Locally
Removed:
使用
cvs
remove
命令删除了该文件,但没有完成提交。
Needs
Checkout:
当前目录没有该文件,而库里有。
你可以使用
cvs
update
命令更新到最新版本。
Needs
Patch:
当前目录的文件版本比库里低,且该文件没有被修改过。
你可以使用
cvs
update
命令自动更新该文件。
Needs
Merge:
当前目录的这个文件版本比库里低,且该文件被修改过。
你可以使用
cvs
update
命令自动合并该文件,然后提交。
但不提倡这样做,应该这样,先把该文件改名,然后使用
cvs
update
将最新的版本提取出来,然后将你的改动加进去再提交。
File had
conficts on merge:
当文件的状态为
Needs
Merge
的时候,你使用
cvs
update
命令去合并它,结果出现冲突,合并失败,你再查该文件的状态,其状态就是
File had
conficts on merge
。
Unknown:
cvs
不能识别该文件,例如你创建了该文件,但没有使用但没有执行过
cvs add
命令。
使用
-v
选项还可以看出这个文件处于哪些分支内:
cvs st –v test1.txt
结果:
File: test1.txt Status:
Up-to-date
Working revision: 1.4
Fri Aug 1 03:37:13
2003
Repository revision: 1.4
/home/casic/cvsroot/pub/testdir1/test1.txt,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
release_08_03_pub_patch_2 (branch: 1.4.4)
release_08_03_pub_patches (branch: 1.4.2)
release_08_03_pub (revision:
1.4)
11)
cvs diff
查看文件的区别。
查看当前文件不同版本之间的区别:
cvs diff –r 1.3 –r 1.5
filename
查看当前文件和库里的最新版本的区别:
cvs diff
filename
12)
cvs export
导出不带
CVS
目录的源代码文件目录树。
cvs export
project_name
13)
cvs logout
在客户端对
CVS
服务器访问完毕,使用该命令退出服务器。
5.
常见操作
1)
通过
cvs
恢复旧版本
如果使用命令
cvs update –r 1.2 filename
这个命令会给
filename
加上一个
Sticky Tag:”1.2”
,虽然你的本意是想把它恢复导
1.2
版本。正确的做法是:
cvs update –p –r 1.2
filename > filename
然后再将
filename
提交。如果不小心已经加成了
Sticky Tag
的话,可以使用命令
cvs update –A
filename
将其恢复到最新版本,然后再采用上面的方面将其恢复为旧版本。
2)
移动文件
/
文件重命名
cvs
里没有
cvs move
或
cvs rename
命令,想要实现该功能可以通过两步来实现:
cvs rm
old_filename
cvs add
new_filename
当然了,每一步都要通过
cvs ci
确认。
3)
删除
/
移动目录
对于删除目录,在上面讲解命令的时候已经讲到过了;至于要移动目录,还是请
CVS
管理员帮你为好。
4)
提取以前版本的项目或分支
首先讲讲怎么样提取以前的版本的项目。通常并不按照版本来提取一个项目,一般是按照时间来的。例如,我要提取
2
个小时以前的项目,可以这样提取:
cvs co –D “2 hours ago”
project_name
这样,
2
个小时前的项目就被提取出来了。最通常使用的时间格式是:
cvs co –D “2003-08-01
10:00:00” project_name
cvs
支持的时间格式很多,还有以下几种:
1 month ago
2 hours ago
400000 seconds ago
last year
last Monday
yesterday
a fortnight ago
3/31/92 10:00:07 PST
January 23, 1987 10:05pm
22:00 GMT
中间有空格符或其他分隔符以至会影响
shell
解释程序的时间格式请用双引号括起来。
不过,根据时间来管理以前的版本,似乎比较麻烦而且容易搞混淆。更好的方法是在项目开发每到一个阶段就打一个标签或建一个分支,这样以后就可以根据这个标签提取以前的代码了。至于怎么打标签,这个最好由
CVS
管理员来做,这里就不介绍怎么打标签了,感兴趣的可以参考另一份文档《
CVS
管理》。
例如,项目发布了
release 1.0
和
release 2.0
,在这两次发布的时候,我们都分别打了标签
project_name_release_1_0
、
project_name_release_2_0
,这样,提取
1.0
和
2.0
版本的时候就可以这样做:
cvs co –r
project_name_release_1_0 project_name
cvs co –r
project_name_release_2_0 project_name
5)
修改一个文件的步骤
我们在修改一个文件并提交的时候,即不希望覆盖别人的改动,也不希望自己的改动被别人覆盖掉。在提交改动的时候,稍不注意就容易出错,这种错误一般不容易察觉,为以后的项目发展埋下隐患。
前面我们讲到过,在不同版本之间进行合并的时候,容易出现冲突,即使不出现冲突,合并的结果也不一定是你想要的。所以我们强烈建议在最新的版本上修改然后再提交。
首先,在你改动之前确保你的文件是最新的:
cvs status
filename
如果不是最新的,使用命令:
cvs update
filename
更新文件到最新版本。然后修改文件准备提交。在提交之前还得先运行命令
cvs status
filename
以确保在你改动期间别人没有改动该文件并提交到库里。如果版本还是最新的,那再运行下列命令提交即可:
cvs update
filename
cvs ci –m
“reason for modification” filename
如果在你改动期间,别人已经改动并提交了该文件,那得把你的文件备份,然后把最新的版本提取出来,再把你的该动加进去,然后提交。
总之,在每次提交之前,都要使用命令
cvs status
查询一下状态,切记!
6.
附录
1)
bash
刚刚建立帐号时,
home
目录下可能还没有环境的配置文件,如果想用
bash
,则要在自己的
home
目录下建立两个文件:
.bash_profile
和
.bashrc
以帐号
dyn
为例,在
/home/dyn
目录下建立文件
.bash_profile
和
.bashrc
,文件的内容如下:
.bash_profile:
#
.bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
unset USERNAME
.bashrc:
#
.bashrc
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
CVSROOT=:pserver:dyn@192.168.0.148:/home/casic/cvsroot; export
CVSROOT
2)
csh
刚刚建立帐号时,
home
目录下可能还没有环境的配置文件,如果想用
csh
,则要在自己的
home
目录下建立一个文件:
.cshrc
以帐号
ynding
为例,在
/home/ynding
目录下建立文件
.cshrc
,文件的内容如下:
.chsrc:
#!/usr/bin/csh
###set path###
set path=( . \
/usr/bin \
/usr/local/arm/2.95.3/bin
\
/usr/local/arm-elf/bin
\
/usr/local/bin \
/usr/bin \
/bin \
/usr/sbin \
/usr/local/sbin
\
/usr/X11R6/bin \
/usr/X11R6/LessTif/Motif1.2/bin \
)
###ENVIRONMENTAL SETTING
setenv CVSROOT /home/casic/cvsroot
###END
umask 027