3.在管理中的相關技術 3.1 在管理源文件的一種技術叫"關鍵字替換".在每次執行"cvs commit"操作後源文件的某些關鍵字會被替換為可用的詞 $AUTHOR$ 用戶名 $Data$ 登記時的時間 $Header$ 標准的首部,包含RCS的完整路徑名,日期,作者 $Id$ 除RCS文件名不完整外與$Header$同. $Log$ 包含RCS的完整路徑名,版本號,日期,作者和在提交時提供的日志信息. $RCSfile$ 包含RCS的文件名,不包括路徑名 $Revision$ 分配的版本號 $Source$ RCS文件的完整名 $State$ 分配的版本的狀態,由 cvs admin -s 分配. 例: 在cvs commit之前,main.c裡有 static char *rcsid="$Id$"; 執行cvs commit後 main.c的改行變為: static char *rcsid="$Id: main.c,v 1.2 1999/04/29 15:10:14 trimblef EXP$"; 當然,這裡只是一個演示.在實際的程序開發中,這種技術有非常有用的作用,在此不多贅述.有興趣的朋友可參考相關書籍. 3.2 創建分支可以使用戶對一些文件使用命令commit進行修改時不會影響主干. 創建分支應首先為擬作修改的那些文件創建一個標簽(tag). 標簽是賦於一個文件或一組文件的符號.在源代碼的生命周期裡,組成一組模塊的文件被賦於相同的標簽.在工作目錄中執行 ~usr/teat/$cvs tag release-1-0 標簽創建後, 就可以為其創建一個分支: ~usr/teat/$cvs rtag -b -r release-1-0 release-1-0-path print -b :創建分支 -r release-1-0 :指定存在的標簽 releas-1-0-patch:分支 print: 模塊名 使用cvs update -j 選項可以將分支上的改變與本地文件拷貝合並. ~usr/teat/$cvs update -j release-1-0 print.c 對源文件作必要修改後, 可以用cvs release 刪除本地工作拷貝 並通知其他開發者這個模塊不再使用. ~use/$cvs release -d test 3.3 沖突解決 在有多個用戶對同一個文件進行修改時,如果修改了其中的相同部分,而修改後的內容如果有不同的話,出現沖突是不可避免的。 例如在CVS 文件倉庫中有一個文件 test.c ,它的版本是 1.4, 用戶A 先檢出該文件進行修改,而稍後有用戶B 檢出該文件進行修改,並提前提交成 1.5,這樣在用戶A再提交時就會出現沖突,這時CVS會提示需要手工解決。 例如,文件倉庫中的版本1.4:內容為: #include main() { int i; for(i = 0; i < 100; i++) printf(“Count: %d ”, i); } 用戶B 1.5: #include main() { int i; for(i = 0; i < 10; i++) printf(“Count: %d ”, i); printf(“Over ”); } 用戶A : #include main() { int i; for(i = 0; i < 50; i++) printf(“Count: %d ”, i); return; } 提交時會提示有沖突,這樣需要手工編輯,這時如果用戶A運行了$cvs update 之後,再編輯test.c, 會看到test.c 的內容是這樣的: #include main() { int i; > 1.5 printf("Count: %d ", i); > 1.5 } 這樣就需要,根據任務的不同,來手工修改,這是比較麻煩的,所以在真正的協作開發中,很少,對同一個文件給與,很多人相同的提交權限. 3.4 文件版本管理 版本管理系統,最重要的莫過於對文件版本的管理,系統默認的版本升級使用的版本號是一定的.如果由於特殊需要,要自己定義出文件的版本號時,你可以用一下命令: cvs log [-lR][-r rev][-d date][-w login][files…] 其中,參數的意義如下: -l 不處理子目錄 -R 對子目錄做同樣處理 -r 指定版本號 -d 指定時間 -w 指定登錄名 使用下面的命令可以參看當前模塊的版本號或指定文件的所有歷史版本信息。 cvs annotate [-lR][-r rev-D date] files 其中,參數的意義如下: -l 不處理子目錄 -R 對子目錄做同樣處理 -r 指定版本號 使用下面的命令可以參看指定文件(檢出之後)的所有修改信息。 $cvs annotate cvstest/c/test.c 輸出依次為:版本 修改人 修改時間 源代碼 1.1 (tang 18-Jan-00): #include 1.1 (tang 18-Jan-00): #include 1.1 (tang 18-Jan-00): 1.1 (tang 18-Jan-00): main() 1.1 (tang 18-Jan-00): { 1.1 (tang 18-Jan-00): int i = 0 ; 1.1 (tang 18-Jan-00): 1.1 (tang 18-Jan-00): for(i = 0; i < 20; i++) 1.1 (tang 18-Jan-00): printf("Count: %d ", i); 1.1 (tang 18-Jan-00): 1.3 (tang 18-Jan-00): printf("222222 "); 1.4 (tang 18-Jan-00): printf("333333 "); 1.1 (tang 18-Jan-00): } 使用下面的命令可以生成相對於一個指定主版本的分支版本: cvs rtag –b –r rev_root rev_branch file_name 其中,參數的意義如下: -b 指定生成一個分支版本 -r 指定該分支的主干節點版本號 rev_root 主干版本號 rev_branch 分支版本號 file_name 指定文件,使用“.”表示當前目錄下所有文件 使用下面的命令可以生成一個對應版本號的分支版本,由於CVS 版本號是用數字表示的,而且在同一個模塊下不同文件的版本完全可能是不同的,所以使用標識會更方便。 例: $cvs rtag –b –r 1.2 tlb-1 SOURCE 以後要訪問該分支版本,可以使用“-r” 選項 $cvs checkout –r tlb-1 SOURCE 從當前檢出的版本切換到一個分支版本: $cvs update –r tlb-1 SOURCE 使用下面的命令可以看版本信息: cvs status [–vlR] files 其中,參數的意義如下: -v 顯示所有信息 -l 不顯示子目錄信息 -R 顯示子目錄信息 命令:cvs update –j rev module 把當前所做的修改與指定版本的文件進行合並。 如:主干 1.1 1.2 1.3 1.4 1.5 1.6 ↓ 分支tlb-1 1.2.2.1 1.2.2.2 1.2.2.3 如果要合並分支tlb-1上的版本: $cvs update –j 1.2.2.3 –j tlb-1 test.c 其中1.2.2.3可以通過tag命令生成一個容易記憶的標識。 如果要合並分支tlb-1到主干上1.2 : $cvs update –j tlb-1 test.c 如果要合並主干上的不同版本(注意順序很重要,同時在指定版本之間的所有修改將被丟棄): $cvs update –j 1.5 –j 1.2 test.c 如果在不同版本之間模塊的文件有增減,則可以: $cvs update –A $cvs updata –jbranch_name 四、命令集 在本章的例子中,介紹了很多,命令的詳細用法,其大多數是以應用的角度,來分析的.實際上.cvs 擁有,大量的命令.如gcc 一樣cvs 常用的命令也不是很多,在本節中,我們列出了一些常用的命令.力圖不和以上各節中介紹的相重復.當然,限於時間和水平,在此也不可能列出cvs 所有的命令.有興趣的朋友.可以,參考,cvs的說明文檔,與Linux 的man文檔,詳細學習,也可來此做出指導 1.檢出源文件 cvs checkout [-r rev][-D date][-d dir][-j merg1] [-j merg2] modules 其中,參數的意義如下: -r 檢出指定版本的模塊 -D 檢出指定日期的模塊 -d 檢出指定目錄而不是模塊 -j 合並當前版本和指定版本 使用下面的命令會檢出剛才生成的模塊,並在當前目錄下生成與文件倉庫中完全一樣的目錄結構: usr$ cvs checkout project usr$ cvs checkou