歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 用CVS來管理自己的程序

用CVS來管理自己的程序

日期:2017/2/27 9:36:25   编辑:更多Linux

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






Copyright © Linux教程網 All Rights Reserved