什麼是 CVS? CVS 是一種客戶機/服務器系統,可以讓開發人員將他們的項目存儲在稱為資源庫的中央位置。使用 cvs 客戶機工具,開發人員可以對資源庫的內容進行更改。CVS 資源庫會依次記錄對每個文件所做的每個更改,並創建一個完整的項目開發進展歷史。開發人員可以請求特定源文件的舊版本、查看更改日志,並根據需要執行其它一些有用的任務。 許多開放軟件項目都有他們自己的 CVS 服務器,項目開發人員把這些服務器作為他們工作的源碼倉庫。源碼倉庫的源碼目錄中保存的都是實現版本控制的歷史文件(history file),歷史文件名為filename,v。歷史文件包含用來恢此邪姹疚募淖愎恍畔ⅰ⑺刑峤壞男畔⒁約疤峤徽咝畔ⅰ@肺募31懷譜鱎CS文件,因為最早是RCS程序用這種格式來保存文件的所有修改信息,可以從man rcsfile得到歷史文件的。 開發人員每天都會改進 CVS 資源庫內的源碼,且他們往往分布在世界各地,而 CVS 提供了一種必要的機制,將他們的項目聯合成一個集中的、協作的整體。CVS 創建了"組織粘和劑",可以讓這些開發人員改進代碼而不會干擾別人、丟失重要數據或遺漏彼此對特定源文件的重要更新。 當開發人員准備好以後,他們把 CVS 上部分當前工作打包成 .tar.gz 文件,作為軟件包的新官方版本來發布它。然而,由於種種原因,最新的官方發行版有時並不是最新的。在本教程的第一部分將首先介紹如何使用CVS為個人使用獲取最新和最高開發人員版本的源碼。 CVSROOT 在開始前,您需要了解一些 CVS 的基礎知識。首先,為了連接到 CVS 資源庫,您需要知道稱為 "CVSROOT" 的路徑。CVSROOT 是一個字符串,就象 URL,它告訴 cvs 命令遠程資源庫在哪裡,以及如何連接它。不僅如此,根據 CVS 資源庫是本地的還是遠程的,以及連接到它的不同方式,CVS 還有許多不同的 CVSROOT 格式。這裡有一些帶有解釋的 CVSROOT 示例。 本地 CVSROOT CVSROOT=/home/cvsroot 這是一個本地 CVSROOT 路徑的示例;如果您想連接到 /home/cvsroot 中存在的本地資源庫,或者有一個經 NFS 安裝在 /home/cvsroot 的資源庫,需要象這樣使用 CSROOOT。 遠程密碼服務器 CVSROOT CVSROOT=:pserver:
[email protected]:/home/cvsroot 這裡是一個遠程資源庫的 CVSROOT 示例,該資源庫位於 foo.bar.com 主機上,並在這台機器的 /home/cvsroot 目錄中活動。前導 ":pserver:" 告訴我們的客戶機使用 CVS 密碼服務器協議連接到這台遠程機器,該協議內置在 CVS 中。一般情況下,公共 CVS 資源庫使用密碼服務器協議以允許匿名用戶訪問。 遠程 rsh/ssh CVSROOT
[email protected]:/data/cvs 這是一個使用 RSH 或 SSH 協議的 CVSROOT 的示例;在該例中,CVS 服務器嘗試使用 drobbing 帳戶來訪問在 foo.bar.com 上的資源庫。如果 CVS_RSH 的環境變量設置成 "ssh",那麼我們的客戶機就嘗試用 ssh 去連接;否則就使用 rsh。那些關注安全性的用戶往往使用 ssh 訪問法;但是,無論是 RSH 還是 SSH 方法都不能對匿名用戶提供一種獲取源碼的方式。為了使用這種方法,您在 foo.bar.com 上必須有個登錄帳戶。 除了 CVSROOT 之外,您還需要知道要檢出的模塊(源碼集合)的名稱,以及登錄到 CVS 密碼服務器的匿名密碼。與匿名 FTP 不同,匿名密碼沒有什麼"標准"格式,所以您需要從開發人員網站或開發人員那裡獲得具體的密碼。一旦知道了所有這些信息,就可以開始了。 與 CVS 交互 獲取源碼需要兩個步驟。首先,以遠程密碼服務器的方式登錄到CVS服務器。然後,使用"checkout"命令獲取源碼。這裡有一組命令的示例,用於檢出最新的 Samba 源碼(一個流行的 UNIX/Windows 集成項目): # eXPort CVSROOT=:pserver:
[email protected]:/cvsroot 第一個命令設置 CVSROOT 環境變量。如果沒有設置這個變量,下面兩個命令將需要跟在 "cvs" 命令後再加上 "-d :pserver:
[email protected]:/cvsroot"。設定 CVSROOT 環境變量省去了一些輸入。 # cvs login (Logging in to
[email protected]) CVS passWord:(在此輸入密碼) # cvs -z5 checkout samba U samba/COPYING U samba/Manifest U samba/README U samba/Read-Manifest-Now U samba/Roadmap U samba/WHATSNEW.txt (這只是完整的 cvs check 輸出的一小段摘錄) 上面第一個 cvs 命令是讓我們登錄到 pserver,第二個命令告訴 CVS 客戶機使用 gzip 壓縮級 5 ("-z5") 在慢速連接上加快傳輸速度,來檢出 ("checkout") samba 模塊。對於每個在本地創建的新文件,cvs 都會打印 "U [path]" 表明這個特定的文件已經在磁盤上更新過了。 一旦檢出命令完成,將在包含最新源碼的當前工作目錄中看到 "samba" 目錄。還會注意到每個子目錄下都有一個"CVS"目錄 -- CVS 在這些目錄中存儲帳戶信息,可以放心地忽略它們。一旦檢出結束,用戶就無需擔心是否設置了 CVSROOT 環境變量,也無需再在命令行上指定它,因為現在所有額外的 "CVS" 目錄裡都有它的緩存。 記住 -- 只需要為初始登錄和檢出設置 CVSROOT。 更新源碼 現在已經有了源碼,就可以繼續編譯和安裝它們、檢查它們,或者對它們執行任何操作。 偶爾,也需要將已檢(checkout)出的源目錄與 CVS 上的當前版本保持同步。為了做到這一點,您無需再次登錄到 pserver;cvs 會將您的認證信息緩存到那些 "CVS"帳戶目錄中。首先,進入主檢出目錄(在這裡是 "samba"),然後輸入: # cvs update -dP 如果有任何新文件,cvs就會在更新每一行的時候輸出 "U [path]" 行。另外,如果本地編譯了源碼,您有可能會看到許多 "? [path]" 行;cvs 指出這些目標文件不來自於遠程資源庫。 另外,請注意我們用於 "cvs update" 的兩個命令行選項。"-d" 告訴 cvs 創建可能已添加到資源庫的新目錄(缺省情況下,這不會發生),"-P" 告訴 cvs 從本地已檢出的源碼副本中除去所有空目錄。"-P" 是個不錯的選擇,因為 cvs 傾向於收集許多隨時間產生的空(曾經使用過,但現在已經放棄)目錄樹。 如果只是要獲得最新的源碼,這些就是您所需要了解的。現在,來看一下作為一個開發人員如何與 CVS 交互。 修改文件 作為一名開發人員,您需要修改 CVS 上的文件。要修改文件,只需要對資源庫的本地副本進行適當的更改。在您明確地告訴 cvs "提交"更改之前,您對源碼做的更改不會應用到遠程資源庫。測試過所有修改以確保它們可以正常運作之後,就可以准備將這些更改運用到資源庫中,遵循下面的兩個步驟。首先,在主源碼目錄中輸入以下命令來更新源碼: # cvs update -dP CVS 合並其他人的更改 我們在前面已經看到,"cvs update"將用資源庫中的當前版本使您的源碼保持最新狀態 -- 但對您已經做過的更改會發生什麼情況呢?不要擔心,它們不會被丟棄。如果另一個開發人員對您沒動過的文件做了一些更改,您的本地文件將進行更新以使它與資源庫中的版本保持同步。 如果您修改了本地文件中的第 1-10 行,而另一個開發人員刪除了第 40-50 行,在文件末尾添加了 12 行新行,同時修改了 30-40 行,然後在您之前他向資源庫提交了他的更改,cvs 會智能地將這些更改合並到您本地已修改的副本中,這樣你們的更改就都不會丟失。這可以讓兩個或更多開發人員針對同一文件的不同部分同時操作。 然而,如果兩個或多個開發人員更改同一文件的同一部分,那麼事情就有些復雜了。如果發生這種情況,cvs 會告訴您有沖突發生。所做的工作不會丟失,但需要手工干預,因為 cvs 需要您提供意見來決定如何合並這些有沖突的更改。 提交 我們過一會兒來看看沖突究竟是如何解決的,但現在,先讓我們假設在輸入 "cvs update -dP" 後沒有沖突 -- 通常都沒有沖突。由於沒有沖突,本地源碼是最新的。可以在主源碼目錄中輸入以下命令來提交對資源庫的更改: # cvs commit 提交所起的作用 "cvs commit" 不只將您的更改應用到資源庫。在真正將您的更改提交給遠程資源庫之前,cvs 會調用缺省編輯器,可以讓您輸入修改的描述。輸入了注解後,保存該文件,退出編輯器,您的更改(和注解)就會應用到遠程資源庫,小組中的其他開發人員可以看到這些更改。 查看日志 要查看某個特定文件完整的歷史以及提交時開發人員(包括您)所加的注解是很容易的。要查看這些信息,輸入: # cvs log myfile.c "cvs log" 命令是遞歸的,所以如果您想查看整個目錄樹的完整日志,只需要進入該目錄,輸入: # cvs log less 提交選項 您可能想要使用另一個輸入 "cvs commit" 時 cvs 在缺省情況下啟動的編輯器。如果是這樣,只需要把您希望使用的編輯器的名稱放進 EDITOR 環境變量中。另外,也可以將更新日志消息作為命令行選項指定,這樣, cvs 就不需要一上來就裝入編輯器: # cvs commit -m I fixed a few silly bugs in portage.py .cvsrc 文件 在繼續了解其它 cvs 命令前,建議設置 ~/.cvsrc 文件。通過在您主目錄中創建 .cvsrc 文件,可以告訴 cvs 在缺省情況下使用您所需的命令行選項,這樣就不必每次都輸入它們。這裡有一個推薦的缺省 .cvsrc 文件: cvs -q diff -u -b -B checkout -P update -d -P 除了為一組 cvs 命令設置有用的選項以外,.cvsrc 的第一行將 cvs 置於安靜模式下,它的主要好處是使 "cvs update" 輸出更簡潔,更具可讀性。另外,一旦完成 .cvsrc 後,就可以輸入 "cvs update" 而不是 "cvs update -dP"。 將文件添加到資源庫 要將源文件添加到 CVS 很容易。首先,用您喜愛的文本編輯器創建該文件。然後,輸入以下命令: # cvs add myfile.c cvs server: use cvs commit to add this file permanently 這將告訴 cvs 在您下次執行 "cvs commit" 時,將該文件添加到資源庫。在那之前,其它開發人員看不它。 將目錄添加到資源庫 將目錄添加到 CVS 的過程類似於: # mkdir foo # cvs add foo Directory /home/cvsroot/mycode/foo added to the repository 與添加文件不同,當您添加目錄時,它會立即出現在資源庫中;不需要 cvs commit。將本地目錄添加到 cvs 後,您會注意到在遠程cvs服務器的對應目錄中創建了一個 "CVS" 目錄,它作為包含 cvs 帳戶數據的容器。因而,您只要看一下其中是否有 "CVS" 目錄,就可以很容易地知道某個目錄是否已添加到遠程cvs服務器的 cvs中了 在將文件或目錄添加到資源庫之前,您必須確保它的父目錄已經添加到 CVS。否則,您會看到類似於下面的錯誤: # cvs add myfile.c cvs add: cannot open CVS/Entries for reading: No sUCh file or directory cvs [add aborted]: no repository 熟悉 "cvs update" 在了解如何解決沖突之前,先讓我們熟悉一下 "cvs update" 命令的輸出。如果創建了一個包含 "cvs -q" 行的 ~/.cvsrc 文件,您會發現 "cvs update" 的輸出相當容易理解。"cvs update" 通過打印單個字符、空格和文件名告訴您它都做些什麼,看到些什麼;如下例所示: # cvs update -dP ? distfiles ? packages ? profiles "cvs update" 用 "?" 字符指示在地副本中找到的這些特殊文件。它們不是資源庫的正式部分,也不是計劃要添加的部分。這裡有一個CVS使用的所有其它單字符信息性消息的列表: U [path] 在本地資源庫中創建新文件,或者更新了您沒有動過的文件時使用。 A [path] 該文件是計劃要添加的,使用 "cvs commit" 時,它被正式添加到資源庫。 R [path] 象 "A" 一樣,"R" 讓您知道該文件計劃要除去。輸入 "cvs commit" 後,該文件就會從資源庫中除去。 M [path] 這意味著您已經修改過該文件了;而且,有可能資源庫中新的更改已成功地合並到該文件。 C [path] "C" 字符表明該文件存在沖突,需要在使用 "cvs commit" 提交更改前手工修改它。 如何解決沖突 現在,讓我們看一下如何解決沖突。我參與了大部分的 Gentoo Linux 項目,我們在 cvs.gentoo.org 上設置了自己的 cvs 服務器。我們這些開發人員花了絕大部分時間來修改 "gentoo-x86" 模塊內部的源碼。在 gentoo-x86 模塊中,有一個叫 "ChangeLog" 的文件,它包含了(您猜一下它)我們對資源庫中該文件做的主要更改的描述。 沖突的示例 因為幾乎每次開發人員對 CVS 進行主要更改時都會對該文件做一些修改,這就成為沖突的主要根源 -- 這裡有沖突的一個示例。假設我在 ChangeLog 的頂部添加了以下行: date 25 Feb 2001 This is the thing I added myself 然而,在我提交這二新行之前,另一個開發人員也在 ChangeLog 的頂部添加了這些行並提交了他的更改: date 25 Feb 2001 This is the part added by another developer 現在,當我運行 "cvs update -dP" (每次提交前您都應該這麼做),cvs 不能把他的更改合並到我的 ChangeLog 本地副本,因為我們倆都向文件的同一部分添加了行 -- cvs 怎麼知道用哪個版本?所以,CVS 會出現以下錯誤: RCS file: /home/cvsroot/gentoo-x86/ChangeLog,v retrieving revision 1.362 retrieving revision 1.363 Merging differences between 1.362 and 1.363 into ChangeLog rcsmerge: warning: conflicts during merge cvs server: conflicts found in ChangeLog C ChangeLog 啊 -- 有沖突!幸好消除這些沖突很容易。如果我啟動我喜愛的文本編輯器,將會在 ChangeLog 文件的頂部看到以下文本: <<<<<<< ChangeLog date 25 Feb 2001 This is the thing I added myself ======= date 25 Feb 2001 This is the part added by another developer >>>>>>> 1.363 cvs 不是選其中一個而捨棄另一個,而是把兩個版本都加進 ChangeLog 文件,並用特殊的分隔符將它們圈起,以明確地標記出有問題的沖突。現在,我要用一個應該出現在 ChangeLog 裡的文本來替換這部分;在這種情況下,替換的文本既不是我的版本也不是他的版本,而是兩者的組合: date 25 Feb 2001 This is the thing I added myself This is the part added by another developer 我用適當的文本替換掉了有沖突的部分(並除去了 "=======" 等標記),可以順利地將我的更改提交給 cvs。 無論什麼時候需要編輯文件來解決沖突時,都要確保已經浏覽過整個文件,以便您知道所有內容;如果您忘記解決某個沖突,那麼在這個沖突解決之前,cvs 是不允許您提交的!很顯然,除去 cvs 添加到沖突文件中的特殊標記是很重要的。 如果您在解決某個沖突時犯了錯誤,然後意外地保存了您所作的更改,那麼您可以在 ".#filename.version" 文件中找到您的原始副本。 刪除文件 現在應該學習關於 CVS 的最後一個技巧 -- 從資源庫中除去文件。除去文件是一個兩階段過程。首先,從源碼的本地副本刪除該文件,然後執行相應的 "cvs remove" 命令: # rm myoldfile.c # cvs remove myoldfile.c 在您下次提交時,該文件計劃將從資源庫中除去。一旦提交,該文件會從資源庫當前的版本中正式刪除。然而, cvs 不會將該文件拋棄,而是仍然完整地保留該文件的內容及其歷史,以備您以後需要它。這只是 cvs 保護您有價值的源代碼的眾多方法之一。 "cvs remove" 是遞歸的,這意味著您可以刪除一批文件,然後從父目錄運行不帶其它自變量的 "cvs remove" 命令。這樣做會在下次提交時標記所有已刪除的文件。 如果您想除去整個目錄,我推薦使用下列過程。首先,從物理上刪除,"cvs remove" 刪除目錄中的所有文件: # rm *.c # cvs remove 然後執行提交: # cvs commit 這裡有一個訣竅。執行以下步驟刪除目錄: # cd .. # cvs remove mydir # rm -rf mydir 請注意,除去目錄不需要另一次提交 -- 把目錄添加到資源庫和從資源庫除去目錄是實時的。 修訂號 源碼倉庫中的一個文件可以有多個版本,同樣一個軟件可能有多個版本。一般在CVS中前一種意義上的版本(源碼倉庫中文件的版本)一般稱為修訂號(revisions),而對軟件的版本一般稱為發布(release)。 一個文件的修訂號一般是依次遞增的,一般以偶數個通過"."連接的十進制數串來表示,如:`1.1, `1.2, `1.3.2.2甚至`1.3.2.2.4.5 標簽的定義和使用 源碼倉庫中各個文件的修訂號是獨立增加的,相互之間沒有任何關聯關系,和軟件的發布號也沒有任何關系,例如一個項目中的各個文件的修訂號可能是這樣的: ci.c 5.21 co.c 5.9 ident.c 5.3 rcs.c 5.12 rcsbase.h 5.11 rcsdiff.c 5.10 rcsedit.c 5.11 rcsfcmp.c 5.9 rcsgen.c 5.10 rcslex.c 5.11 rcsmap.c 5.2 rcsutil.c 5.10 為了便於標記,可以使用標簽來為某個特定版本的特定文件設定一個標記以方便訪問,可以使用cvs tag和cvs rtag來定義標簽,其中cvs tag用來為倉庫中當前工作文件(或文件集合)指定一個符號標記;cvs rtag用來顯式地為源碼倉庫的特定修訂號的文件定義一個標記。例如下面的例子就是給文件backend.c的當前修訂號定義一個標簽,然後察看該文件的狀態: $ cvs tag rel-0-4 backend.c T backend.c $ cvs status -v backend.c =================================================================== File: backend.c Status: Up-to-date Version: 1.4 Tue Dec 1 14:39:01 1992 RCS Version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none) Existing Tags: rel-0-4 (revision: 1.4) 但是在實際應用中很少會為特定文件定義一個標簽,而往往是在開發過程中的特定階段為特定項目的所有文件定義一個標簽,以方便發布或者定義分支,例如: $ cvs tag rel-1-0 . cvs tag: Tagging . T Makefile T backend.c T driver.c T frontend.c T parser.c 定義標簽以後,可以在隨後的任何時候訪問對應該標簽的項目文件,例如下面這個命令就用來實現檢出對應於標簽rel-1-0的所有文件(可能是軟件的1.0發布): $ cvs checkout -r rel-1-0 tc 可以想像標簽為聯系特定修訂號文件的曲線索引,例如: 這裡表示在軟件開發過程中的定義了標簽*,也可這樣看待標簽: 當然也可以刪除標簽,例如: cvs rtag(/tag) -d rel-0-4 tc 刪除模塊tc的rel-0-4標記 備份源碼倉庫 備份: 首先斷開所有的cvs連接,然後使用cp命令備份即可 分支 通過CVS可以實現將對源碼的修改提交給一個獨立的開發線,被稱為分支(branch)。當對分支的文件進行修改時,這些修改不會對主分支和其他分支產生影響。 隨後可以將將一個分支的修改合並(merging)到其他分支。合並是通過cvs update -j來合並修改到當前工作目錄(本地),然後就可以提交修改來影響其他分支了。 分支的重要性 讓我們假設這種情況,項目tc的1.0版本已經搞定,你將繼續開發tc項目,計劃在幾個月內發布1.1版本,但是客戶抱怨軟件中有致命的錯誤。因此你檢出1.0版本(這裡就是需要使用標記的原因)並發現了這個bug的原因。然而當前的源碼處於1.0和1.1版本之間因此代碼處於混亂狀態,而且在一個月內不大可能出現穩定版本,因此不大可能根據當前的版本得到一個修復錯誤的版本來發布。 對於這種情況這就需要創建一個包含錯誤修改的1.0分支發布,而不需要影響當前的開發,在合適的時候可以將修正合並的主發布中去。 創建分支 創建分支首先為擬修改的某些文件創建一個標簽(tag),標簽是賦於一個文件或一組文件的符號.在源代碼的生命周期裡,組成一組模塊的文件被賦於相同的標簽。 創建標簽:在工作目錄裡執行cvs tag 。 例: 為src創建標簽: cvs checkout src(/update亦可,用來更新本地的源代碼) cvs tag release-1-0(為當前最新源碼加一個標簽) 標簽創建後, 就可以為其創建一個分支: cvs rtag -b -r release-1-0 release-1-0-path print -b :創建分支 -r release-1-0:-r參數用來標記那些包含指定的標簽的文件 releas-1-0-patch:分支 print: 模塊名 可以使用tag -b來創建分支,例如在工作目錄中: $ cvs tag -b rel-1-0-patches 將會基於當前工作的分支分離一個分支,並將該分支命名為`rel-1-0-patches。應該理解分支是在cvs的源碼倉庫中創建的,而不是當前工作目錄,基於當前修正創建分支不會將當前工作拷貝自動轉換為新的分支,需要手工來實現的。也可以通過使用rtag命令實現不涉及工作目錄的分支: $ cvs rtag -b -r rel-1-0 rel-1-0-patches tc `-r rel-1-0指示創建的新分支應該以標記`rel-1-0指定的修訂為基礎,而不是基於當前的工作主分支。這主要是用來從舊版本中創建一個分支(例如上面的例子)。 rtag -b指示創建分支(而不是僅僅創建標記)。應該注意的是`rel-1-0包含的各個文件的修訂號可能是不一樣的。 所以該命令的效果是為工程tc創建一個新分支-名字為`rel-1-0-patches,以標記`rel-1-0為基礎。 訪問分支 可以以兩種方式訪問分支:從源碼倉庫中檢出分支代碼,或者將當前的工作拷貝切換為分支。 從源碼倉庫中創檢出新分支可以使用命令checkout -r release-tag命令: $ cvs checkout -r rel-1-0-patches tc 將當前分支切換到分支命令: $ cvs update -r rel-1-0-patches tc 或者 $ cd tc $ cvs update -r rel-1-0-patches 隨後的提交等影響源碼倉庫的操作都僅僅對分支起作用,而不會影響主分支和其他分支。可以使用status命令來察看當前工作拷貝屬於哪個分支。輸出中察看sticky tag信息,這就是cvs顯示當前工作拷貝是在哪個分支上: $ cvs status -v driver.c backend.c =================================================================== File: driver.c Status: Up-to-date Version: 1.7 Sat Dec 5 18:25:54 1992 RCS Version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v Sticky Tag: rel-1-0-patches (branch: 1.7.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: rel-1-0-patches (branch: 1.7.2) rel-1-0 (revision: 1.7) =================================================================== File: backend.c Status: Up-to-date Version: 1.4 Tue Dec 1 14:39:01 1992 RCS Version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v Sticky Tag: rel-1-0-patches (branch: 1.4.2) Sticky Date: (none) Sticky Options: (none) Existing Tags: rel-1-0-patches (branch: 1.4.2) rel-1-0 (revision: 1.4) rel-0-4 (revision: 1.4) 不要被每個文件的分支號碼不同(`1.7.2和`1.4.2)所迷惑,分支是由分支標記來決定的這裡都是 rel-1-0-patches。這裡的分支號僅僅表示當生成該分支時每個文件的修訂號。 分支和修訂號 通常情況下源碼庫中文件的修訂號是以線性增大的: +-----+ +-----+ +-----+ +-----+ +-----+ ! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 ! +-----+ +-----+ +-----+ +-----+ +-----+ 但是CVS並不局限於線性開發,源碼樹可能出現分支,每個分支是一個對立的開發線。對分支的修改會很容易地被加入到主分支中來。 每個分支都擁有一個分支號,由使用"."分隔的奇數個數組成的數串來表示。分支號是通過在產生分支處的修訂號後添加一個整數來實現得到的。通過定義分支號使得從同一個分支點分出多個開發分支成為可能。 分支的修訂號是通過在分支號後順序添加數字後綴得到的,如下圖所示: 分支號產生的詳細細節其實是不必詳細了解的,但是了解其工作原理是必要的:當CVS創建一個分支時,其選擇一個最小的偶數作為分支號後綴。因此當希望從修訂號6.4分出一個分支時,新分支的分支號為6.4.2。所有以0作為分支號後綴的分支號都被CVS自己保留使用(例如6.4.0)。 合並分支 分支開發一段時間以後往往需要將修訂合並到主分支中來,可以通過`-j branchname參數實現合並分支。使用該參數將分支和其父分支合並。 考慮下面的源碼修訂樹: 分支1.2.2被定義為標記R1fix。下面的例子假設模塊mod僅僅包含一個文件m.c: $ cvs checkout mod #獲取最新的1.4版本 $ cvs update -j R1fix m.c # 合並分支的所有更新到主分支 # 也就是1.2到1.2.2.2的修改合並到當前工作拷貝 $ cvs commit -m "Included R1fix" # 創建修訂版本1.5. 合並時可能出現沖突情況,如果發生沖突,應該在提交以前手工處理沖突。 檢出命令(checkout)命令同樣支持參數 `-j branchname,上面的操作可以通過下面的命令實現; $ cvs checkout -j R1fix mod $ cvs commit -m "Included R1fix" 一個需要注意的問題是"update -j tagname"同樣能 參考資料: http://www.cvshome.org/docs/manual/cvs.Html