每個編寫程序的人也許都有過這樣的體驗:對編寫的程序作了一些修改,幾天以后,我們可能發(fā)現(xiàn)上次的修改導致了其它的矛盾,甚至編譯不能通過,但這時我們卻很難找到自己剛在哪里作了改動。一般說來,我們總是希望自己完整的記錄下一個程序開發(fā)的過程,記錄下這個程序的每一點改進和調(diào)整。或許我們可以用備份的方法來解決這個問題,于是我們建立一個backup的目錄,定期或不定期的將自己的源程序打包放進去,直到某一天整個硬盤都被這些文件撐滿。這當然有些夸張,但這種機制帶給我們的不方便是顯而易見的。更進一步,現(xiàn)在一個軟件產(chǎn)品的開發(fā),一個人單槍匹馬很難完成。可能是包含幾個、幾十個乃至上百個程序員協(xié)作開發(fā),這時的源代碼又該如何管理?解決問題的方法就是使用CVS。
CVS - Concurrent Versions System(并發(fā)版本管理系統(tǒng))是一個版本控制管理系統(tǒng),它是目前最為廣泛使用的一個系統(tǒng)。從gftp到gtk到KDE,你幾乎可以在每一個你熟悉的自由軟件的源碼里看到它的蹤跡(下面我們會知道,它的蹤跡指一個稱為cvs的子目錄)。同樣,你也可以在幾乎每一個Linux的發(fā)行版本里看到CVS系統(tǒng)。可以說,如果失去了CVS,現(xiàn)有的許多多人協(xié)作、自由開發(fā)的軟件都會在一定程度上放慢自己發(fā)展的步伐。 CVS到底有哪些功能,使得它有如此強大的魅力呢?
1.CVS能做什么?
如上所說,CVS首先是一個版本管理系統(tǒng),它可以保留軟件開發(fā)過程中的每一個版本的信息,包括誰、在何時、作了什么樣的修改以及為什么作這樣的修改等。這個功能和以前流行于Linux和Unix的版本管理系統(tǒng)RCS(Revision Control System)和SCCS(Source Code Control System)很象。但CVS的功能遠非僅此。它的最大的特點是它的并發(fā)性,即它支持分布式項目的開發(fā)。在互聯(lián)網(wǎng)席卷一切的今天,這個功能太為重要了。小到一個辦公室內(nèi)部開發(fā)一個OA系統(tǒng),大到KDE小組利用互聯(lián)網(wǎng)開發(fā)新版本的KDE,CVS都可以一展身手。一個程序員開發(fā)出了自己負責模塊的新版本后,迅速的通過CVS讓開發(fā)組的每一個成員都分享自己的最新成果。甚至,CVS通過特定的機制允許多個程序員同時修改同一個源程序文件。
另外CVS增強的目錄結(jié)構(gòu)以及對二進制文件良好的處理,都使得它遠遠優(yōu)于其它的版本管理系統(tǒng)。最后,必須一提的是CVS是基于RCS開發(fā)而成的。
2.如何得到CVS?
CVS在幾乎包含在所有的Linux發(fā)布版本中,如RedHat、Turbo Linux、Slackware以及國產(chǎn)的紅旗、Xteam Linux等。你可以試著敲一下cvs命令,大多數(shù)情況下都會出現(xiàn)以Usage: cvs開頭的一堆信息,提示你如何使用cvs,這意味著在你的機器上早已有了CVS,只是遺憾的是它一直未被你發(fā)現(xiàn)和利用。運氣不好的話,你會看到形如cvs: Command not found.的提示,這意味著你的機器沒有安裝CVS。這時你有兩種選擇。一是找到你的Linux安裝盤,從那里安裝CVS。例如在使用RPM方式安裝的Linux(上面介紹的幾個發(fā)布版本中似乎除了Slackware,其他都是)發(fā)布版本中,找到cvs***.rpm,用rpm命令進行安裝。第二種方式是到一些站點cvs的源代碼,然后遵循里面附帶的指導進行安裝,需要的讀者請訪問站點www.cyclic.com/或者http://www.loria.fr/~molli/cvs-index.html。
3.CVS的基本使用方法
在這一節(jié)里,我們來學習掌握CVS的一些基本使用方法。現(xiàn)在我們假定已經(jīng)安裝好了CVS,并且我們打算用它來管理自己正在開發(fā)的一個軟件,軟件名叫netants,它存放在硬盤上一個叫做netants的目錄里,目前里面有了文件netants.c、netants.h、http.c、http.h和Makefile。我們并沒有和它人協(xié)作開發(fā)這個軟件,也沒有利用Internet或者Intranet來開發(fā)這個軟件。或許,它只是自己的一個業(yè)余作品,試圖寫出一個比Windows下的網(wǎng)絡(luò)螞蟻更好的下載工具出來。
3.1初始化CVS
我們首先要使用的命令是cvs init,這個命令用來初始化CVS系統(tǒng)。正如我們所看到的,所有的CVS命令都以cvs開頭,然后在后面緊跟命令、參數(shù)和一些選項。初始化CVS系統(tǒng)主要是為了創(chuàng)建一個為CVS所使用的源碼儲存庫(repository)。創(chuàng)建的時候,需要指定在那個目錄下創(chuàng)建這個源碼儲存庫。有兩種方法來指定目錄。一是利用"-d "選項來指定,例如:-d /usr/local/cvsroot。另一種更方便的方法是在shell里設(shè)定一個名叫CVSROOT的環(huán)境變量。使用csh或者tcsh的用戶可以使用命令setenv來設(shè)定,在文件.csh rc或者文件.tcshrc里添加入下的一行: setenv CVSROOT /usr/local/cvsroot 使用sh或者bash的用戶需要在文件.profile或者文件.bashrc里添加如下兩行: CVSROOT=/usr/local/cvsroot export CVSROOT 設(shè)置了環(huán)境變量CVSROOT后,我們運行命令cvs init,CVS將在指定的目錄下面建立自己所需要的一些文件,以后我們使用CVS管理的任何項目,都會被CVS儲存在這個目錄之下。不過千萬要注意的是:永遠不要去試圖修改這個目錄下的文件。這個目錄是由CVS自己進行管理的,輕率的改動可能會導致你丟失你部分或全部的交由CVS管理的源代碼或其他資源。
3.2導入項目到CVS中去
初始化結(jié)束以后,我們就要真正開始利用CVS來管理自己的程序網(wǎng)絡(luò)螞蟻了。第一步,我們將這個項目交由CVS管理。使用如下的CVS的import命令,將源程序?qū)氲紺VS的源碼儲存庫中去: cd netants cvs import -m "start my project: Netants" netants yoyo start 這個命令看起來有些復雜,需要解釋一下。import是cvs的導入命令,默認狀況下,它循環(huán)的將當前目錄下的所有文件(包括子目錄)導入到源碼庫(即CVSROOT指定的目錄)里去。-m "start my project: Netants"告訴CVS你對這一步操作的說明。這是CVS強制要求的,如果你沒有使用這種-m "字符串"的選項,CVS將會彈出一個文本編輯器(如果自己不特別指定的話,在Linux下一般是vi,而在Windows下則是Notepad),讓你輸入一些說明信息它才罷休。netants是這個項目被CVS存儲時的路徑名,即CVS將在創(chuàng)建一個$CVSROOT/netants的目錄,并在此目錄下存放此項目的文件,當然,它不是原封不動的存儲,CVS會做一番處理。最后兩個字符串設(shè)定了兩個標記(tag),現(xiàn)在并沒有什么用處,但它們同樣是CVS指定必需的,所以我們添上這兩個參數(shù)。執(zhí)行此命令時,CVS自動將所有的文件版本設(shè)為1.1,這是它所認為的最低版本。以下為執(zhí)行上述命令后的顯示信息:N netants/netants.c N netants/http.c N netants/http.h N netants/netants.h N netants/Makefile No conflicts created by this import N表示New,CVS成功的加載了這些文件,并沒有發(fā)現(xiàn)沖突。 上面的命令稍長了一些,而且顯得有些繁瑣,相信我,CVS不總是這樣的,這點"繁瑣"相對它給我們帶來的便利是完全可以忽略不計的。
3.3從CVS中導出項目
好了,我們把自己的netants的項目交給了CVS去管理,現(xiàn)在,我們完全可以刪除原有的存儲我們代碼的netants目錄(當然,安全起見,你或許應(yīng)該再做一次備份,并希望是最后一次)。我們要進行開發(fā)工作了,建一個目錄,叫什么呢,就叫worktmp吧。我們進到此目錄下,執(zhí)行命令cvs checkout netants,我們將會看到如下的信息:cvs checkout: Updating netants U netants/Makefile U netants/http.c U netants/http.h U netants/netants.c U netants/netants.h CVS在當前目錄下建立一個叫做netants的目錄,我們原先的代碼文件都在這個目錄下出現(xiàn)了,而且還多了一個名為CVS的目錄。目錄CVS下面存放的是一些文本文件,記錄了CVSROOT的位置、此項目對應(yīng)源碼庫中那個目錄等一些信息。
3.4保存修改到CVS中
現(xiàn)在,我們開始艱苦卓越的編程工作。經(jīng)過數(shù)十分鐘、數(shù)小時乃至數(shù)天的工作,我們對原有的代碼做了較大的修改,現(xiàn)在要告一段落了。我們將修改的內(nèi)容提交給CVS,于是,我們需要執(zhí)行命令 cvs commit -m "Made some useful changes on some files" 這時,我們將會看到CVS給出一些提示信息,它掃描并比較此目錄下的現(xiàn)有文件和它在源碼庫中保存的原有文件,做了修改的文件將被更新,并且有了新的版本號:1.2。-m參數(shù)如同前面所說,是為了不想它啟動一個文本編輯器來讓自己輸入。如果我們僅是修改了其中一兩個文件,我們可以在上面的命令的最后附上文件名,這樣CVS只會比較、更新指定的文件。注意的是,和自己做備份不同,CVS只是保存了不同版本之間的差異,并沒有完整的保存各個版本。現(xiàn)在,你是不是覺得CVS有點用處了。
3.5添加文件到項目中
有一天,我們開始考慮給我們的網(wǎng)絡(luò)螞蟻加上從ftp站點下載文件的功能,于是,我們需要在原有的項目里添加兩個文件:ftp.c和ftp.h。首先,我們在工作目錄下建立并編輯、修改、生成了這兩個文件,然后我們使用命令add命令來添加。 cvs add ftp.c ftp.h 此時,文件并沒有真正的被添加,只是相當于"注冊"了一下,要使這個過程生效,我們?nèi)匀恍枰褂胏ommit命令: cvs commit ftp.c ftp.h -m "Add two files: ftp.c and ftp.h" 此時,CVS將把這兩個文件添加到項目中去,他們的版本均為初始的1.1。 3.6從項目中刪除文件
除了添加以外,我們有的時候可能需要刪除某個文件,例如我們發(fā)現(xiàn)文件netants.h其實沒有什么用。于是,我們執(zhí)行下面幾個命令來完成刪除工作: rm netants.h cvs remove netants.h cvs commit netants.h -m "Delete a file." 要注意的是,CVS只是刪除了當前版本的netants.h,它以前的版本依然存在,除非它恰好僅有1.1版本。
3.7設(shè)定特定版本號
經(jīng)過一段時間的工作,程序已經(jīng)初具規(guī)模,形成了較穩(wěn)定的版本。這個時候,netants.c可能已經(jīng)是5.4版本,而http.c可能是3.5版本,而我們希望將當前的代碼作一個版本發(fā)布。此時,我們需要使用的是tag命令。這個命令賦予指定的一個或多個文件一個給定的文本形式的版本號。版本號必須以字母開始,可以包含數(shù)字、下劃線和連接符號(-)。我們想給當前項目的所有文件賦予相同的版本號時,可以不指定文件或路徑參數(shù),CVS默認選擇當前目錄下所有在CVS中注冊的文件(循環(huán)進子目錄)。下面既是一個例子: 鍵入命令:cvs tag release0-1 提示信息: cvs tag: Tagging . T Makefile T ftp.c T ftp.h T http.c T http.h T netants.c 這樣當前版本的所有文件都有了一個叫做release0-1的版本代號。當我們需要這個版本的時候,我們使用-r (版本代號)參數(shù)來得到指定的版本。例如命令: cvs checkout -r release0-1 netants 將在當前目錄下建立netants目錄,并導出所有版本代號為release0-1的文件。
3.8更新當前工作目錄中的文件
這里使用的命令為update,它將比較指定的在CVS源碼庫中的文件和當前目錄下的文件,如果CVS源碼庫中有更高版本的源文件,則更新當前目錄下的文件。這個功能主要是多人協(xié)作開發(fā)項目時使用的,讓你及時分享同伴的工作成果。但它另外一個重要的用途,同樣適用于單人開發(fā)的項目。這個用途需要使用-j參數(shù),我們看下面的例子: cvs update -j 1.5 -j 1.3 netants.c 這個命令的功能是,在當前目錄的netants.c文件中,忽略從版本1.3到版本1.5所作的修改。毫無疑問,對程序員來說,這是一個非常重要的功能。因為在某個階段我們對程序所作的修改在現(xiàn)在可能會被視為是無效乃至錯誤的,這個功能很好的解決了這個問題。 在更新的過程中,CVS執(zhí)行一個自動合并的過程。例如我們的工作目錄中的netants.c文件版本是2.1,并且我們已經(jīng)對此文件作了一番修改,而CVS源碼庫中的是版本2.2,此時我們執(zhí)行update命令時,CVS并不是簡單的將版本2.2覆蓋版本2.1,而是試圖將自版本2.1到版本2.2的修改添加到當前目錄中的文件中去,如果它和我們剛剛所作的修改有沖突,則CVS會以字符串">>>>"表示由沖突發(fā)生,期待用戶去修改。CVS拒絕接受包含有上述特定字符串的文件。下面即是一個沖突的例子:netants.c:版本號2.2,保存在CVS中……getPartFile( ); showFinished(); return(A); }……
netants:版本號2.1經(jīng)過我們的修改……getPartFile( ); return(B); }……我們執(zhí)行命令cvs update netants.c后,將會包含如下內(nèi)容的新的netants.c:
……getPartFile( ); showFinished(); >>>>>> 2.2 }…… 除非我們做出修改并刪去">>>>>>",否則在執(zhí)行cvs commit的時候,netants.c將不會更新原有的2.2版本。
4.CVS的其他功能
CVS當然遠不止上面所說的這些內(nèi)容,這些僅是CVS的基本功能,CVS還有許多重要的功能,如上面所說的網(wǎng)絡(luò)工作方式、支持二進制文件等。下面我們對這些功能作簡單的說明。
4.1 CVS的網(wǎng)絡(luò)工作方式
CVS的網(wǎng)絡(luò)功能采用client-server結(jié)構(gòu),兩地均需安裝CVS。CVS采用rsh方式或者口令校驗方式進行工作。對client端,同前面講過的設(shè)置環(huán)境變量CVSROOT一樣,用戶需要設(shè)置新的環(huán)境變量CVS_SERVER,指明CVS在server上的路徑,例如:/usr/local/cvsroot1。CVS的-d參數(shù)指定路徑名,它后面可以用:(local或server或ext):來指明是在本地還是在異地服務(wù)器上,默認當然是在本地,正如我們在初始化CVS一節(jié)所使用的那樣。下面的命令假定我們的CVS服務(wù)器為cvs.rdcps.ac.cn,用戶名為crazyyao,CVS源碼庫在服務(wù)器的/usr/local/cvsroot1目錄下,我們的工作項目還是netants,我們用rsh方式導出項目文件: cvs -d : server : crazyyao@cvs.rdcps.ac.cn :/usr/local/cvsroot1 checkout netants 采用口令校驗方式時,需要對修改系統(tǒng)文件/etc/inetd.conf,以便使inetd知道如何分配、處理CVS Server的請求和響應(yīng)。CVS會在源碼庫所在的目錄中創(chuàng)建一個名為passwd的口令文件,對用戶進行校驗。使用口令校驗時,CVS支持匿名登陸,而且CVS項目超級用戶可以設(shè)置項目中文件的存取權(quán)限。 關(guān)于如何配置CVS使之工作在網(wǎng)絡(luò)方式下的詳細信息請參考CVS的文檔。
4.2 CVS的分支和融合功能
CVS增強的目錄工作方式使得CVS提供分支和融合功能。有的時候,當項目進展到一定程度時,可能需要暫時中斷,去做另外一些修改和發(fā)展。例如,我們的軟件原有版本為1.0,并已提交用戶使用,現(xiàn)在正在開發(fā)2.0。某一天,1.0的用戶發(fā)現(xiàn)了一個較大的bug或者需要添加某個短小的功能,這時我們不能讓用戶去期待2.0版本,又必須給用戶滿意的答復,比較理想的解決方式是把現(xiàn)在的工作先放到一邊,另開一個分支,去滿足用戶的需要。當此分支完成后,程序源還可以使用CVS的融合功能將這一部分修改添加到我們開發(fā)2.0版本的主工作進程中去。 創(chuàng)建分支可以使用tag -b命令。例如下面的命令 cvs tag -b netants-1-0-patch 在當前的工作目錄的基礎(chǔ)上創(chuàng)建一個叫做netant-1-0-patch的分支。 融合的命令參數(shù)是-j,我們在前面已經(jīng)提及它了。
4.3 CVS處理二進制文件的功能
CVS可以保存二進制文件,但和文本文件相比,它的許多功能喪失了。對于文本文件,CVS可以辨別出文件的任何一點改動,但對于二進制文件它無能為力。但是,CVS可以區(qū)分出文件作了改動,并會提示用戶自己修改、保存。與文本文件不同,CVS保存二進制文件每個版本的完整信息。在操作二進制文件時,需要添加參數(shù)-KB,以便告訴CVS不把它當作文本文件看待。
4.4 CVS比較文件的功能
執(zhí)行的命令為diff,這個功能和shell下的diff功能基本一樣。例如下面的命令比較CVS源碼庫中的最新的netants.c文件和當前目錄下netants.c文件有什么不同: cvs diff netatns.c
5.結(jié)束語
通過上面的介紹,希望能激起大家使用CVS的興趣,并掌握使用CVS的一些基本方法。碰到困難時,別忘了翻閱CVS附帶的手冊,不過,它有厚厚的172頁。希望CVS能加速你的軟件開發(fā)。
http://51cmm.csai.cn/casepanel/CM/No047.htm