在多人共同開發(fā)一個大型項目時,源代碼的維護和版本維護是一件令人頭疼的事情,由于多人開發(fā),每個開發(fā)人員都擁有此項目的副本,所以如果要手動維護同一個文件多人的修改是十分困難的事情。
另外,可能你需要的項目的版本不是當前開發(fā)的新的版本, 如果為了這個目的而為每一個版本保留一個備份幾乎是不可能的。Linux平臺上提供了一個功能軟件:CVS。眾所周知,Linux的發(fā)展得益于互聯(lián)網(wǎng)的發(fā)展,大部分的軟件都是眾多開發(fā)者在互聯(lián)網(wǎng)上共同開發(fā)的,這些軟件的維護大部分都使用CVS,例如Deban Linux的開發(fā)、KDE的開發(fā),以及sourceforg上的開發(fā)項目。正確熟練使用CVS是一個Linux程序員基本的素質(zhì)。
CVS不僅可以維護源代碼,事實上,所有的文本文件都可以使用CVS來管理,當然也可以管理 二進制文件,只是需要特殊的命令選項罷了。
CVS把文件保存在一個名叫倉庫(repository)的地方,倉庫中保存的文件并不是每個版本的副本,而是可以從任意版本回溯到初始版本的一些代碼的主控信息,這樣,節(jié)省了大量的存儲空間。
倉庫不僅可以建立在本機上,也可以建立在網(wǎng)絡(luò)上。另外CVS支持版本分支(tag),這樣可以從任意的版本中衍生出另外一個版本進行開發(fā),必要時,還可以把這個分支合并到主開發(fā)分支去。
CVS需要一個名叫RCS(修訂控制系統(tǒng))的軟件,確切說,CVS主要管理開發(fā)項目中的目錄的改動,而RCS則側(cè)重于管理的一個文件的改變。如果要使用網(wǎng)絡(luò)的CVS,還需要rsh或者自己內(nèi)置的cvs-server,rsh是CVS客戶于服務(wù)器的通信平臺,如果需要安全的信息傳輸,可以使用ssh,這個可以使用CVS_RSH環(huán)境變量來指定:
export CVS_RSH=rsh 使用rsh
export CVS_RSH=ssh 使用ssh
RCS使用
在使用CVS之前,先介紹一下RCS的使用方法。
正如前面所說,RCS是針對某一個特定的文件進行管理,常用到的命令是co和ci。RCS使用當 前工作路徑下的RCS目錄來存儲管理的文件。
ci (check in)把源代碼加入到RCS源代碼倉庫中,每一個添加進代碼庫中的文件的版本是 1.1。
以后每次修改文件重新ci以后,此文件的版本遞增為1.2 ,1.3.……。
co(check out)把源文件從RCS源代碼倉庫中取出,缺省的版本是新的版本,如果你需要一個指定的版本,則需要使用-r選項指定。例如:
$mkdir RCS 建立RCS源代碼倉庫
編輯一個文件,如hello.c
#include <stdio.h>
int main (void)
{
printf ("Hello World
");
return 0;
}
然后把它加入到RCS倉庫中:
[kerberos@power zhyf]$ ci hello.c
RCS/hello.c,v <-- hello.c
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>>the inital verion. 輸入關(guān)于文件改動的信息
>> . 以.結(jié)束信息輸入
initial revision: 1.1 初始版本是1.1
done
[kerberos@power zhyf]$
當文件加入到源代碼倉庫后,RCS會自動刪除文件。
如果需要修改文件,則從倉庫取出:
[kerberos@power zhyf]$ co hello.c
RCS/hello.c,v --> hello.c
revision 1.1
done
此時,取出的文件是只讀的,如果需要編輯文件,需要對文件加鎖取出,防止與他人編輯沖突!
加鎖取出使用-l (lock)選項。
[kerberos@power zhyf]$ co -l hello.c
RCS/hello.c,v --> hello.c 從RCS倉庫中取出hello.c,倉庫中的文件是以v結(jié)尾的。
revision 1.1 (locked) 指明是加鎖取出
done
這時,我們可以修改和編輯文件了。
例如:
#include <stdio.h>
int main (void)
{
printf ("Hello World
");
printf("checkoutwithlock
"); 添入代碼
return 0;
}
[kerberos@power zhyf]$ ci hello.c
RCS/hello.c,v <-- hello.c
new revision: 1.2; previous revision: 1.1 重新加入到倉庫,文件版本遞增為1.2
enter log message, terminated with single '.' or end of file:
>> check out with lock and modified it .
>> .
done
如果你需要先前的hello.c,也是1.1版本的,可以使用-r來指定取出文件的版本:
[kerberos@power zhyf]$ co -l -r1.1 hello.c
hello.c,v --> hello.c
revision 1.1 (locked) 取出1.1版本
done
可以嘗試使用兩次加鎖取出,這時候,RCS會提示警告信息。
[kerberos@power zhyf]$ co -l hello.c
hello.c,v --> hello.c
revision 1.1 (locked)
writable hello.c exists; remove it? [ny](n) 是否覆蓋當前的hello.c
如果回答n,則取出失敗,回答是則覆蓋當前文件與-l相反的選項是-u,取出不加鎖的文件用于工作。-f則在ci時強制覆蓋RCS倉庫中的文件,在co時強制覆蓋當前的文件。
在RCS中,支持類似于宏的關(guān)鍵字,在ci后,這些關(guān)鍵字會被RCS替換成特定的信息,如$Id$關(guān)鍵字:
/*$Id
*/
#include <stdio.h>
int main (void)
{
printf ("Hello World
");
printf("checkoutwithlock
");
return 0;
}
ci 之后,然后取出,文件將變成:
/*$Id: hello.c,v 1.3 2001/02/22 16:16:58 kerberos Exp kerberos $
*/
#include <stdio.h>
int main (void)
{
printf ("Hello World
");
printf ("check out with lock
");
return 0;
}
$Id$ 關(guān)鍵字是用文件名、版本、時間、作者 及代碼性質(zhì)替換,如果使用-l選項取出,在Exp后面會加上登錄用戶的名稱。除了$Id$關(guān)鍵字,RCS還支持下面常用的關(guān)鍵字:
$Log$ : 你所提供的修改日志信息。
$Author$ :存入該版本的作者。
$Locker$ : 該版本的加鎖者
$State$ : 該版本的狀態(tài) Exp(試驗版), Stabe(穩(wěn)定版), Rel(發(fā)行版).缺省是Exp
$Date$ : 該版本存入的時間,使用UTC時間格式。
$Revision$ : 該版本的版本號
$RCSfile$ : RCS文件名
$Source$ : RCS全路徑名
$Name$ : 取回該版本的符號名
$Header$ : 相當于$ Source $$ Revision$$Date$$Author $$State$$Locker$的組合在UNIX/Linux下有一個diff工具可以比較兩個文件的不同,rcsdiff可以在不同的版本之間比較文件的不同,而不必取出文件,如:
rcsdiff hello.c 比較當前hello.c文件與RCS倉庫中新版本的區(qū)別。
rcsdiff -r1.1 hello.c 比較當前hello.c文件與hello.c的1.1版本的區(qū)別。
rcsdiff -r1.2 -r1.1 比較hello.c 文件的1.1版本和1.2版本的區(qū)別。
使用這個命令,可以很方便的做出任意版本之間的補丁文件。
另外,還有其他一些不常用的RCS命令,讀者可以參考更詳細的資料。