CVS 是 Concurrent Version System(并行版本系統(tǒng))的縮寫,用于版本管理。在多人團(tuán)隊(duì)開發(fā)中的作用更加明顯。CVS 的基本工作思路是這樣的:在一臺(tái)服務(wù)器上建立一個(gè)倉(cāng)庫(kù),倉(cāng)庫(kù)里可以存放許多不同項(xiàng)目的源程序。由倉(cāng)庫(kù)管理員統(tǒng)一管理這些源程序。這樣,好象只有一個(gè)人在修改文件一樣。避免了沖突。每個(gè)用戶在使用倉(cāng)庫(kù)之前,首先要把倉(cāng)庫(kù)里的項(xiàng)目文件下載到本地。用戶做的任何修改首先都是在本地進(jìn)行,然后用 cvs 命令進(jìn)行提交,由 cvs 倉(cāng)庫(kù)管理員統(tǒng)一 修改。這樣可以做到跟蹤文件變化,沖突控制等等。
由于CVS是建立在在原先 Unix 體系里很成熟的 SCCS 和 RCS 的基礎(chǔ)上,所以CVS多是Linux(UNIX)系統(tǒng)中所使用,本文中服務(wù)器端設(shè)置也是以Linux為例。
一、CVS服務(wù)器的安裝
首先確認(rèn)系統(tǒng)中是否安裝CVS服務(wù):
[root@localhost /]# rpm -qa|grep cvs
cvs-1.11.2-cvshome.7x.1
如果命令輸出類似于上面的輸出則說(shuō)明系統(tǒng)已經(jīng)安裝有cvs,否則需要從安裝光盤中安裝cvs的rpm包,或者到http://www.cvshome.org下載。
1、建立 CVSROOT
目錄,因?yàn)檫@里涉及到用戶對(duì)CVSROOT里的文件讀寫的權(quán)限問題,所以比較簡(jiǎn)單的方法是建立一個(gè)組,然后再建立一個(gè)屬于該組的帳戶,而且以后有讀寫權(quán)限的用戶都要屬于該組。假設(shè)我們建一個(gè)組叫cvs,用戶名是cvsroot。建組和用戶的命令如下
#groupadd cvs
#adduser cvsroot
生成的用戶宿主目錄在/home/cvsroot(根據(jù)自己的系統(tǒng)調(diào)整)
2、用cvsroot 用戶登陸,修改 /home/cvsroot (CVSROOT)的權(quán)限,賦與同組人有讀寫的權(quán)限:
$chmod 771 . (或者770應(yīng)該也可以)
注意:這一部分工作是按照文檔說(shuō)明做的,是否一定需要這樣沒有試驗(yàn),我會(huì)在做試驗(yàn)后在以后版本的教程說(shuō)得仔細(xì)一點(diǎn)。如果您有這方面的經(jīng)驗(yàn)請(qǐng)?zhí)峁┙o我,謝謝。
3、建立CVS倉(cāng)庫(kù),(仍然是 cvsroot 用戶),用下面命令:
$cvs -d /home/cvsroot init
4、以root身份登陸,修改 /etc/inetd.conf(使用 xinetd 的系統(tǒng)沒有此文件)和 /etc/services
如果用的是 inetd 的系統(tǒng),在 /etc/inetd.conf 里加入:
cvsserver stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/home/cvsroot pserver
說(shuō)明:上面的行是單獨(dú)一整行,/usr/bin/cvs 應(yīng)該是你的cvs版本的命令路徑,請(qǐng)根據(jù)自己的系統(tǒng)調(diào)整./home/cvsroot是你建立的CVSROOT的路徑,也請(qǐng)根據(jù)上面建立目錄的部分的內(nèi)容做調(diào)整。
如果是使用 xinetd 的系統(tǒng),需要在 /etc/xinetd.d/ 目錄下創(chuàng)建文件 cvspserver(此名字可以自己定義),內(nèi)容如下:
# default: on
# description: The cvs server sessions;
service cvsserver
{
socket_type = stream
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=/cvsroot pserver
log_on_failure += USERID
only_from = 192.168.0.0/24
}
其中only_from是用來(lái)限制訪問的,可以根據(jù)實(shí)際情況不要或者修改。修改該文件權(quán)限:
# chmod 644 cvspserver
在/etc/services里加入:
cvsserver 2401/tcp
說(shuō)明:cvsserver 是任意的名稱,但是不能和已有的服務(wù)重名,也要和上面修改 /etc/inetd.conf 那行的第一項(xiàng)一致。
5、添加可以使用 CVS 服務(wù)的用戶到 cvs 組:
以 root 身份修改 /etc/group,把需要使用 CVS 的用戶名加到 cvs 組里,比如我想讓用戶 laser 和gumpwu 能夠使用 CVS 服務(wù),那么修改以后的 /etc/group 應(yīng)該有下面這樣一行:
cvs:x:105:laser,gumpwu
在你的系統(tǒng)上GID可能不是105,沒有關(guān)系。主要是要把laser和gumpwu用逗號(hào)分隔開寫在后一個(gè)冒號(hào)后面。當(dāng)然,象RedHat等分發(fā)版有類似linuxconf這樣的工具的話,用工具做這件事會(huì)更簡(jiǎn)單些。
6、重起inetd使修改生效:
#killall -HUP inetd
如果使用的是 xinetd 的系統(tǒng):
# /etc/rc.d/init.d/xined restart
然后察看cvs服務(wù)器是否已經(jīng)運(yùn)行:
[root@localhost /]# netstat -lnp|grep 2401
tcp 0 0 0.0.0.0:2401 0.0.0.0:* LISTEN 1041/xinetd
則說(shuō)明cvs服務(wù)器已經(jīng)運(yùn)行。
二、管理CVS服務(wù)器
服務(wù)器可以用了,現(xiàn)在大家關(guān)心的是如何管理服務(wù)器,比如,我想讓一些人有讀和/或?qū)?CVS 倉(cāng)庫(kù)的權(quán)限,但是不想給它系統(tǒng)權(quán)限怎么辦呢?
不難,在 cvs 管理員用戶(在我這里是 cvsroot 用戶)的家目錄里有一個(gè) CVSROOT 目錄,這個(gè)目錄里有三個(gè)配置文件,passwd, readers, writers,我們可以通過(guò)設(shè)置這三個(gè)文件來(lái)配置 CVS 服務(wù)器,下面分別介紹這幾個(gè)文件的作用:
passwd:cvs 用戶的用戶列表文件,它的格式很象 shadow 文件:
{cvs 用戶名}:[加密的口令]:[等效系統(tǒng)用戶名]
如果你希望一個(gè)用戶只是 cvs 用戶,而不是系統(tǒng)用戶,那么你要設(shè)置這個(gè)文件,剛剛安裝完之后這個(gè)文件可能不存在,你需要以 cvs 管理員用戶手工創(chuàng)建,當(dāng)然要按照上面格式,第二個(gè)字段是該用戶的加密口令,是用 crypt (3)加密的,你可以自己寫一個(gè)程序來(lái)做加密,也可以用我介紹的偷懶的方法:先創(chuàng)建一個(gè)系統(tǒng)用戶,名字和 cvs 用戶一樣,口令是準(zhǔn)備給它的 cvs 用戶口令,創(chuàng)建完之后從 /etc/shadow 把該用戶第二個(gè)字段拷貝過(guò)來(lái),然后再把這個(gè)用戶刪除。這個(gè)方法對(duì)付數(shù)量少的用戶比較方便,人一多不合適了,而且還有沖突條件(race condition)的安全隱患,還要 root 權(quán)限,實(shí)在不怎么樣。不過(guò)權(quán)益之計(jì)而已。寫一個(gè)小程序并不難,可以到 linuxforum 的編程版搜索一下,有個(gè)朋友已經(jīng)寫了一個(gè)貼在上面了。
第三個(gè)字段是等效系統(tǒng)用戶名,實(shí)際上是賦與一個(gè) cvs 用戶一個(gè)等效的系統(tǒng)用戶的權(quán)限,看下面的例子你明白它的功能了。
readers:有 cvs 讀權(quán)限的用戶列表文件。是一個(gè)一維列表。在這個(gè)文件中的用戶對(duì) cvs只有讀權(quán)限。
writers:有 cvs 寫權(quán)限的用戶的列表文件。和 readers 一樣,是一個(gè)一維列表。在這個(gè)文件中的用戶對(duì) cvs 有寫權(quán)限。
上面三個(gè)文件在缺省安裝的時(shí)候可能都不存在,需要我們自己創(chuàng)建,好吧,現(xiàn)在還是讓我們用一個(gè)例子來(lái)教學(xué)吧。假設(shè)我們有下面幾個(gè)用戶需要使用 cvs:
laser, gumpwu, henry, betty, anonymous。
其中 laser 和 gumpwu 是系統(tǒng)用戶,而 henry, betty, anonymous 我們都不想給系統(tǒng)用戶權(quán)限,并且 betty 和 anonymous 都是只讀用戶,而且 anonymous 更是連口令都沒有。那么好,我們先做一些準(zhǔn)備工作,先創(chuàng)建一個(gè) cvspub 用戶,這個(gè)用戶的責(zé)任是代表所有非系統(tǒng)用戶的 cvs 用戶讀寫 cvs 倉(cāng)庫(kù)。
#adduser
...
然后編輯 /etc/group,令 cvspub 用戶在 cvs 組里,同時(shí)把其它有系統(tǒng)用戶權(quán)限的用戶加到 cvs 組里。(見上文)
然后編輯 cvs 管理員家目錄里 CVSROOT/passwd 文件,加入下面幾行:
laser:$xxefajfka;faffa33:cvspub
gumpwu:$ajfaal;323r0ofeeanv:cvspub
henry:$fajkdpaieje:cvspub
betty:fjkal;ffjieinfn/:cvspub
anonymous::cvspub
注意:上面的第二個(gè)字段(分隔符為 :)是密文口令,你要用程序或者用我的土辦法生成。
編輯 readers 文件,加入下面幾行:
anonymous
betty
編輯 writers 文件,加入下面幾行:
laser
gumpwu
henry
注意:writers中的用戶不能在readers中,要不然不能上傳更新文件。
對(duì)于使用CVS的用戶要修改它的環(huán)境變量,例如laser用戶的環(huán)境變量,打開/home/laser(laser的宿主目錄)下的.bash_profile文件,加入
CVSROOT=/home/cvsroot
export CVSROOT
用laser登陸可以建立CVS項(xiàng)目,如果要root使用,可以修改/etc/profile文件。
現(xiàn)在我們各項(xiàng)都設(shè)置好了,那么怎么用呢,我在這里寫一個(gè)簡(jiǎn)單的(估計(jì)也是常用的)命令介紹:
首先,建立一個(gè)新的CVS項(xiàng)目,一般我們都已經(jīng)有一些項(xiàng)目文件了,這樣我們可以用下面步驟生成一個(gè)新的CVS項(xiàng)目:
進(jìn)入到你的已有項(xiàng)目的目錄,比如叫 cvstest:
$cd cvstest
運(yùn)行命令:
$cvs import -m "this is a cvstest project" cvstest v_0_0_1 start
說(shuō)明:import 是cvs的命令之一,表示向cvs倉(cāng)庫(kù)輸入項(xiàng)目文件。 -m參數(shù)后面的字串是描述文本,隨便寫些有意義的東西,如果不加 -m 參
數(shù),那么cvs會(huì)自動(dòng)運(yùn)行一個(gè)編輯器(一般是vi,但是可以通過(guò)修改環(huán)境變量EDITOR來(lái)改成你喜歡用的編輯器。)讓你輸入信息,cvstest 是項(xiàng)目名稱(實(shí)際上是倉(cāng)庫(kù)名,在CVS服務(wù)器上會(huì)存儲(chǔ)在以這個(gè)名字命名的倉(cāng)庫(kù)里。)
v_0_0_1是這個(gè)分支的總標(biāo)記。沒啥用(或曰不常用。)
start 是每次 import 標(biāo)識(shí)文件的輸入層次的標(biāo)記,沒啥用。
這樣我們建立了一個(gè)CVS倉(cāng)庫(kù)了。
建立CVS倉(cāng)庫(kù)的文件夾應(yīng)該是“干凈”的文件夾,即只包括源碼文件和描述的文件加,而不應(yīng)該包括編譯過(guò)的文件代碼等!
三、使用CVS
winCVS是一個(gè)很好的CVS客戶端軟件,在http://cnpack.cosoft.org.cn/down/wincvsdailyguide.pdf可以下載到這個(gè)軟件的使用手冊(cè)。這里不在贅述了。
四、用CVS管理項(xiàng)目
本人正在一加公司從事該公司ERP項(xiàng)目的開發(fā),在沒有使用CVS的時(shí)候,多次出現(xiàn)了由于不同的開發(fā)人員修改同一程序,而導(dǎo)致程序錯(cuò)誤,解決版本控制問題迫在眉睫。
由于這個(gè)項(xiàng)目采用Linux平臺(tái)下JAVA開發(fā),使用的開發(fā)工具Jbulider是支持CVS進(jìn)行項(xiàng)目管理的,作為主程序員,我決定采用CVS進(jìn)行版本控制,首先參照上文在Linux服務(wù)器上建立了CVS服務(wù),然后我把我本地的工程文件傳至服務(wù)器。
例如:我的工程文件在F:ERP下,我把ERP下的erp.jpx文件、defaultroot文件夾和src文件夾上傳至服務(wù)器/usr/local/erp下,然后登陸Linux服務(wù)器,登陸的用戶是CVS的用戶,其環(huán)境變量要正確(我的用戶名為admin)
#cd /usr/local/erp
#cvs import -m "this is a ERP project" erp v_0_0_1 start
這樣名為erp的CVS倉(cāng)庫(kù)建立了。
之后開發(fā)小組的成員可以用winCVS把該項(xiàng)目下載到本地:
打開winCVS
點(diǎn)擊工具欄Create -> Create a new repository... 彈出窗口
在Grenral中
Enter the CVSROOT填寫admin@192.168.1.9:/home/cvsroot其中admin是cvs的用戶,在本例中admin也是linux的系統(tǒng)用戶,192.168.1.9是服務(wù)器的地址,/home/cvsroot是CVS的主目錄,參考上文。
Authentication中選擇"passwd file on the cvs server"
Use version中選擇cvs 1.10 (Standard)
其它項(xiàng)默認(rèn)即可。
確認(rèn)后,點(diǎn)工具欄Admin --> Login... 會(huì)提示輸入密碼,輸入密碼后,看看winCvs的狀態(tài)欄。如果提示
*****CVS exited normally with code 0*****
表示登錄正常。
點(diǎn)擊工具欄Create --> Checkout module...彈出對(duì)話框,其中的Checkout settings項(xiàng)中
Enter the module name and path on the server 填寫erp,即我們建立的名為erp的CVS倉(cāng)庫(kù)
Local folder to checkout to 選擇要下載到本地的目錄,我選了F:myerp
其它項(xiàng)目可以默認(rèn),確定后可以下載到本地了,在F:myerp下會(huì)有一個(gè)erp文件夾,其文件結(jié)構(gòu)和F:erp下的文件結(jié)構(gòu)是一樣的。
用Jbulider打開F:myerperp下的erp.jpx文件,這個(gè)工程文件可以使用了。
在Jbuilder的工具欄Team --> Select Project VCS 彈出對(duì)話框,選擇CVS
對(duì)于你要進(jìn)行修改的文件,在Project View中點(diǎn)中該文件,然后點(diǎn)右鍵,探出快捷菜單,選擇CVS --> CVS Edit "xxxx.java(文件名)"
第一次使用可能會(huì)提示CVS服務(wù)器的密碼。
在修改之前還要選擇CVS --> Update "xxxx.java(文件名)"
修改之后選擇CVS --> Commit "xxxx.java(文件名)"
這樣,修改的文件保存到CVS服務(wù)器了,Update的目的是下載、比較文件。每次在修改之前都Update,保持新版本。
CVS在項(xiàng)目管理使用中確實(shí)起到了良好的效果,仔細(xì)研究CVS的命令,可以更好的發(fā)揮CVS在版本控制上的能力。