最近加入公司一個新的團隊,發現他們使用的原始碼版本控制軟體是CVS,感覺自己有點倒退了,因為之前一直用的是SVN來進資料列版本設定的,平時自己也愛折騰折騰Hg,Git等分布式版本控制軟體。和一個開發經理閑聊時順便瞭解了一下,為何一直使用CVS而不是SVN或直接上Hg、Git。那個同學很謙虛的告訴我,CVS確實有很多問題,但是這麼一直使用過來,如果換成SVN,感覺帶來的好處不足夠大。
但是有趣的是,這位同學用CVS的方式也很特別,就是使用CVS+本地Hg的方式進行管理。具體方式是目錄A同時使用CVS和Hg,同一份代碼在目錄B使用Hg,目錄B的修改push到目錄A,在頻繁的Hg push,最終完成某個功能或Bug修複後,再通過CVS將改動提交到伺服器。(實際使用方式更複雜,他還同時還在另外一台Linux機器用Hg管理,然後與目錄A目錄B同步。)
這樣做的好處是可以避免頻繁的入庫CVS,保證每次提交都是一個完整的功能或Bug修複,同時本地又留有每次微小變更的記錄。 不過這樣的確有些累。
關於CVS和SVN的具體區別,我之前並沒有認真研究過,所以我沒辦法說服那位同學,而且他可能比我還專業。考慮到以後我還要在CVS上幹活,於是搜了一下相關的文章,找到一篇寫的不錯的,瞭解一下,可就是找不到原文出處,就直接貼下來了,如果以後知道出處,一定示出。
以下是轉帖內容:
CVS SVN VSS 使用對比
一、Subversion包含絕大部分CVS功能
Subversion 作為CVS 的重寫版和改進版,其目標就是作為一個更好的版本控制軟體,取代目前流行的CVS。Subversion 的主要開發人員都是業界知名的CVS 專家。Subversion支援絕大部分的CVS 功能/命令;Subversion 的命令風格和介面也與CVS 非常接近。當然,不同的地方正是對CVS 的改進。
二、全域性的版本編號
一個新的版本,並得到一個自增量的版本號碼N+1,該版本號碼並不針對某個特定的檔案,而是全域性的、針對整個版本庫的。因此,我們可以將Subversion 的版本庫看作是一個檔案系統或檔案分類樹的數組。
從技術的角度來說,在Subversion 中,"檔案foo.c 的第5 版本"這個說法是錯誤的;正確的說法應該是:"檔案foo.c 在版本庫被修改了5 次,即執行5 次commit 後是什麼樣子?"。顯然,在Subversion 中,版本庫被修改5 次後foo.c 的內容,和被修改了6 次後foo.c 的內容很可能完全一樣,因為版本庫的第6 次修改很可能只修改了版本庫的其他部分,而並沒有對foo.c 的進行修改。相反,在CVS 中,檔案foo.c 的第1.1 版本和第1.2 版本總是不同的。
Subversion 的全域性版本編號為Subversion 帶來了諸多的優勢:如對目錄或檔案執行拷貝,無論涉及多少檔案,Subversion 不需要對單個檔案依次執行拷貝命令,僅僅需要建立一個指向相應的全域版本號碼的一個指標即可。
三、目錄的版本控制
CVS 只能對檔案進資料列版本設定,不能對目錄進資料列版本設定,因此CVS 沒有任何關於檔案"移動"(move)操作的概念。當人為進行檔案移動操作時,CVS 只能注意到,一個檔案在一個位置被刪除了,而在一個新位置建立了另外一個檔案。由於它不會串連兩個操作,因此也很容易使檔案曆史軌跡丟失。設定 CVS 存放庫時,必須非常謹慎地為每個檔案選擇準確的位置,因為在設定之後,幾乎就要一直使用這個位置了。
同樣由於CVS 不記錄目錄的版本曆史,CVS 不支援對檔案的"重新命名"(rename),人為的對檔案進行重新命名會使得命名前後的檔案失去曆史聯絡,而記錄曆史本來是版本管理的主要目的。
還有,CVS 不支援對檔案的"拷貝"(copy),人為的拷貝對CVS 而言,只能看到新的檔案的增加,而不能記錄拷貝源檔案和目標檔案之間的聯絡。
綜上所述,缺乏對檔案"移動"、"重新命名"、"拷貝"的支援的根源在於CVS 不能記錄目錄的版本曆史,而這些操作在當前的軟體開發過程中經常發生,這正是Subversion被開發並取代CVS 的主要原因之一。
Subversion 將目錄作為一類特殊的檔案來處理(事實上,從檔案系統的角度來看,目錄確實是一類特殊的檔案,當目錄中的子目錄/檔案被刪除、重新命名、或新的子目錄/檔案 被建立時,目錄的內容將發生改變)。因此,Subversion 象記錄普通檔案的修改曆史一樣記錄對目錄的修改曆史,當發生檔案/目錄的移動、重新命名或拷貝操作時,Subversion 能夠準確記錄操作前後的曆史聯絡。同樣,象對檔案的不同曆史版本進行比較一樣,Subversion支援對目錄的不同曆史版本的比較,清晰展現目錄的變化 曆史。
四、原子性提交
從使用者的角度來看,CVS 和Subversion 都支援對多個檔案修改的批量提交,但二者在實現方式上存在本質的區別。
CVS 採用線性、串列的批量提交,即依次地,一個接一個地執行提交,每成功提交一個檔案,該檔案的一個新的版本即被記錄到版本庫中,提交時使用者提供的日誌資訊被重複地儲存到每一個被修改的檔案的版本曆史中。
CVS 串列批量提交模式的弊端在於 -當任何原因造成大量操作的中斷時(典型原因包括:網路中斷、用戶端死機等),版本庫往往處於一個不一致的狀態:原本應該全部入庫的檔案只有一部分入庫, 很有可能版本庫中的最新版本不能順利編譯,更為嚴重的是,隨著其他的使用者執行cvs update 操作,該不一致性將迅速在Team Dev中擴散,從而嚴重影響團隊的開發效率,並存在品質隱患。另外,假如該批量提交的中斷沒有被及時發現,Team Dev往往要花更 多的時間進行軟體調試和排錯。
CVS 即使在批量提交不發生中斷時也會造成不一致:假設使用者A 啟動一個需要較長時間才能完成的批量提交;與此同時,使用者B 執行cvs update 操作。此時,使用者B 很有可能得到一個不一致的更新,即使用者B 通過"更新"操作,得到使用者A 的部分修改檔案。
Subversion 徹底消除了CVS 的以上弊端。無論批量提交包含多少檔案修改,只有當全部檔案修改都成功入庫,該提交才變得有效,才對其他使用者可見;否則,無論任何原因造成中 斷,Subversion 都會自動執行"復原"(rollback)操作。換一個說法,Subversion 保證所有的修改要麼全部入庫生效,要麼一個也不入庫,即對版本庫不作任何的修改。這就是Subversion 的原子性提交(atomic commit)。
由於Subversion 的原子性提交特性和全域版本編號方式,當提交成功完成時,一個唯一的、新的全域版本編號產生,而提交時使用者提供的日誌資訊與該新的版本編號關聯,只進行一次儲存(區別於CVS 的按檔案重複儲存)。
五、支援變更集概念
由於Subversion 的所有提交是原子性的,每次成功提交形成的唯一的全域版本號碼對應此次批量提交的所有檔案修改,也就是說,一個Subversion 版本號碼其實對應了一個邏輯上的變更集(change set),該變更集可能對應於對一個BUG 的修複,或者對應於對一個已有功能的改進,或者對應於一個新功能的實現。可以說,變更集是一個軟體開發活動的邏輯結果,該變更集可以通過其對應的版本號碼在 軟體開發的其他過程中(如軟體合并/整合過程,軟體發行管理,變更管理系統,缺陷追蹤系統)被引用。因此,Subversion 將版本管理從單純的、單個的檔案修改的層次通過邏輯上的抽象,上升到更便於理解和交流的開發活動的層次。
六、差異化的二進位檔案處理
由於曆史原因,CVS 主要是為早期的程式員設計的,CVS 能夠有效處理文字檔(或ASCII檔案,原始碼檔案),可以對文字檔進行差異化的儲存、新舊版本的比較,檔案合并等;但對於二進位檔案,CVS則明顯 力不從心。在CVS 的版本庫中,對於二進位檔案的曆史版本,CVS 唯一能做的就是對不同的版本進行獨立的、冗餘的儲存,哪怕版本之間其實只存在微小的差異。舉例而言,一個10M 的二進位檔案(照片、圖形檔案、機械設計檔案、電子設計檔案)假如每周修改一次,無論每次修改的大小,一年下來,僅該檔案就要消耗500M 以上的儲存空間。而且,用戶端每次擷取該檔案的新版本都要消耗10M 的網路流量。
對於目前的Team Dev,無論是軟體開發,Web 網站的開發,手機等電子產品的研發,需要進行版本管理的不僅是原始碼等文字檔,還需要管理需求文檔、設計文檔、測試文檔、使用者手冊,圖形影像檔,機械/電子設計檔案等諸多的二進位檔案,CVS 顯然不是一個好的選擇。
與CVS 不同,Subversion 採用統一的二進位差異演算法(binary differencing algorithm),即對文字檔和二進位檔案採用相同的差異比較演算法,並以相同的方式在版本庫中進行儲存:每次提交後版本庫中只儲存相對於先前版本的 差異,從而可以節省大量的儲存空間。
該二進位差異演算法不僅應用在版本的儲存上,更為重要的是,Subversion 對二進位檔案與文字檔一視同仁,當用戶端需要擷取新的版本時(如執行svn update),在網路上只有版本的差異被傳輸,從而大大減少對網路頻寬的消耗。更多細節參見"七、雙向的差異化-壓縮網路傳輸"。
七、 雙向的差異化-壓縮網路傳輸
如上所述,CVS 對二進位檔案不能進行有效差異化處理。對於文字檔,CVS 僅僅支援單向的差異化傳輸:從CVS 到用戶端的傳輸是差異化的,即執行cvs update 時,只有差異的部分從伺服器傳輸到用戶端;而當執行cvs commit 時,無論代碼變化多少,CVS 都需要從用戶端向伺服器完整傳輸被修改檔案的全部內容,不能只傳輸差異。
相反,無論是文字檔還是二進位檔案,Subversion 都進行雙向的差異化傳輸,並且差異化內容還要進行壓縮/解壓縮的過程:在伺服器端擷取差異顯而易見,與CVS 類似;Subversion 在用戶端擷取差異的秘密在於 — Subversion 在用戶端的工作拷貝中隱含了每個檔案的一個"唯讀、乾淨的"副本(該副本隱藏在隱含目錄.svn 裡,通常不可見,該副本還有更多的妙用,參見"十二、更多的本地/離線操作"),通過比較使用者在用戶端的修改和該隱含的副本,Subversion 擷取需要真正傳送到伺服器的差異,並對差異進行壓縮後才進行網路傳輸。
對CVS 而言,操作的成本(網路頻寬消耗是最大的操作成本)與被修改的檔案的大小成比例,而與修改本身的大小無關;對Subversion 而言,操作成本只與修改本身的大小成比例,而與被修改的檔案的大小無關。因此,與CVS 相比,Subversion 消耗更少的網路頻寬(以用戶端的儲存空間換取更少的頻寬消耗在目前的計算環境下應該是個相當不錯的選擇!)。Subversion 更加適合基於互連網(或廣域網路)進行協作開發的地理上分布的團隊 — 版本伺服器集中、單一;用戶端廣泛分布。
八、高效、快捷建立分支和基準
CVS 和Subversion 都支援分支(branch)和基準(tag),通過分支與合并,可以有效支援大項目的並行開發模式;通過基準管理,可以準確標識一組檔案的版本,有效進行軟體發行管理和必要時的曆史回溯。
但CVS 和Subversion 在實現分支和基準的方式上存在很大的不同。CVS 在建立分支的時候,需要對所有進行分支的檔案進行依次的操作,因此分支的建立成本(主要是建立分支所需的時間,或消耗的計算資源)與參與分支的檔案數量成 比例,項目越大,版本庫越大,檔案越多,分支的建立成本越高;基準(tag)的建立與此類似。
Subversion 的分支和基準是通過執行"拷貝"來建立的:回想一下在沒有引入版本管理工具的時候我們是如何進行所謂的"分支"和"基準"管理的?答案顯然是"拷貝" — 我們通過"拷貝"或"備份"來建立基準;同樣,為支援多個開發人員可以同時進行開發,我們為每個開發人員建立一份"拷貝"。由此看 來,Subversion 通過"拷貝"來建立分支和基準顯得非常自然,有點"返樸歸真"的意思。
由於Subversion 的全域版本號碼特性,Subversion 中分支或基準的建立過程,或Subversion中的"拷貝"過程,真正的操作是在版本庫中建立一個到某一全域版本號碼的指標(pointer),不再需要 針對眾多的單個檔案依次執行操作。因此,該操作的成本為一個很小的常數,與項目大小,版本庫大小,檔案數目的多少無關;並且,分支或基準的建立不需要進行 版本的冗餘儲存,建立立的分支或基準基本不佔用版本庫空間,分支的後續儲存空間的開銷也只與修改的大小有關。
九、整合Apache Web Server,提供更多的特性
Subversion 通過與Apache Web Server 的整合,可以提供基於http/https 協議的版本庫訪問機制,從而支援Subversion 跨越防火牆的安全訪問。除此以外,Subversion 還可以利用更多的Apache 特性,包括但不限於:Apache 豐富的使用者認證機制(包括通過LDAP伺服器如Windows Active Directory 伺服器的使用者認證),基於目錄路徑的精細粒度的存取控制,對傳輸的網路流量進行壓縮/解壓縮,瀏覽版本庫目錄結構等等。
十、支援WebDAV
WebDAV(Web-based Distributed Authoring and Versioning)是一種基於 HTTP 1.1 協議的通訊協定.它擴充了HTTP 1.1,在GET、POST、HEAD 等幾個HTTP 標準方法以外添加了一些新的方法,使應用程式可直接對Web Server 直接讀寫,並支援寫檔案鎖定(Locking)及解鎖(Unlock),還可以支援檔案的版本控制。
Microsoft windows2000/XP 及IE, Office 還有Adobe/MicroMedia 的DW 等都支援WebDAV,這又大大增強了Web 應用程式的價值,以及效能。對於需要大量發布內容的使用者而言,應用WebDAV 可以降低對CMS 系統的依賴,而且能夠更自由的進行創作。上傳、下載變得輕鬆自如。
Subversion 通過與Apache Web Server 的整合,支援WebDAV 協議,使得業務使用者(business users)或非技術使用者在不安裝任何版本管理用戶端的情況下輕鬆訪問Subversion 版本庫,不改變業務使用者已有使用習慣,支援分布的業務使用者對文檔的評審、修改並實現版本控制,真正將軟體開發的生命週期從開發/技術團隊擴充到項目的全部 干係人(stakeholder),避免通過電子郵件傳遞文檔的混亂與無序、通過Windows 作業系統共用造成的安全性漏洞、病毒攻擊、曆史版本被覆蓋或丟失、審計困難等諸多典型問題。
十一、更好的衝突標識與處理
CVS 和Subversion 都支援通過分支與合并進行並行開發,並可以自動檢測到合并時的衝突(conflicts),並在合并結果中 以<<<<<< … >>>>>>標識合并的衝突部分。
在CVS 中,經常會出現由於使用者的疏忽(如,沒有注意到衝突,或沒有完全處理好衝突)而將仍然帶有<<<<<< … >>>>>>衝突標識符號的檔案直接進行提交(commit),從而在版本庫中產生垃圾版本。
Subversion 有效解決了CVS 的以上問題:Subversion 記錄並保持檔案的衝突狀態,只有當使用者明確執行svn resolved 命令後,該衝突狀態標識才被複位,該檔案才能被提交,從而大大減少了將仍然帶有<<<<<< … >>>>>>衝突標識符號的檔案直接進行提交的可能性。
十二、 更多的本地/離線操作
眾所周知,CVS 用戶端的工作拷貝中包含了一個隱含目錄CVS,該目錄中記錄了用戶端需要的一些管理資訊;與此類似,Subversion 的用戶端工作拷貝中也包含了一個隱含目錄.svn,該目錄中同樣記錄了用戶端需要的一些管理資訊,如版本庫URL,當前訪問版本號碼等。
與CVS 不同的是,Subversion 的.svn 目錄中還包含了工作拷貝中每一個檔案的一個"唯讀、乾淨的"副本。正是由於該副本的存在,使得Subversion 與CVS 相比,可以執行更多的本地/離線操作,即某些操作不需要訪問版本程式庫伺服器,因此不需要存在從用戶端到伺服器的網路連結,當然也不消耗任何網路頻寬,這進一 步增強了Subversion 對廣域網路的友好支援。
Subversion 的以下命令可以進行離線操作:
svn status - 顯示工作拷貝上的本地修改概況;
svn diff -顯示工作拷貝上的本地修改細節,比較修改前後的內容;
svn revert - 撤銷工作拷貝上的本地修改;
十三、 對符號連結進行版本管理
在Unix 檔案系統中,符號連結(symbolic links,包括永久連結和軟連結)是一種重要的檔案系統元素。CVS 不能對符號連結進行版本管理;Subversion 則可以對符號連結進行版本管理。
十四、 中繼資料管理
與CVS 相比,Subversion 增加了中繼資料(metadata)管理機制。即可以對版本庫中的檔案或目錄附加任意的"屬性"(property),並記錄屬性的變化曆史,也就是對元數 據進行版本管理。一個Subversion 屬性是一個"屬性名稱/屬性值"的二元組,如"BugNumber= 100"就是一個屬性,可以將該屬性附加到版本N 上,以說明版本N 改正了編號為100的BUG。
Subversion 中繼資料的目的是提供附件的資訊以滿足流程或過程自動化的需要,以增強Subversion 的管理能力和自動化程度。Subversion 自身就通過"屬性"來儲存一些特殊的資訊。一個使用Subversion 中繼資料的例子:可以在一些批處理的指令碼程式或Subversion的鉤子程式(hooks)中建立、訪問、修改"屬性"中繼資料來滿足流程自動化的要求。
十五 VSS CVS 比較
VSS適合小團隊使用,基本的組態管理功能都有。VSS最大的特點就是部署比較簡單,上手比較快。VSS最大的缺點就是安全性問題,目錄共用、檔案方式儲存等。當然VSS還只能在Windows下使用。
CVS瞭解過,應該說特點也很鮮明。首先CVS是開源軟體,根據長期的流傳,已經演變了很多版本,適合於不同的平台。因此,在CVS用戶端上是多種多樣的。其次,CVS的部署稍微複雜點,現對VSS來說,這是其一缺點。最後,CVS在組態管理的理念上,比VSS有所進步。
十六 Vss與Svn 的對比
1. SVN支援重新命名,這對 Java開發來說非常重要。
為了得到更好的代碼,開發中需要經常進行重構,重構就經常涉及到檔案的重構名,而重新命名中 VSS 中是不被支援的。
2. 開發的時候不一定要鎖定。
一方面導致重構不方便,另一方面,不能離線開發,使用 SVN 就不同,可以帶回家繼續開發,回來後,提交就行了。
3. 多平台。
可以支援多個平台下的操作
4. 更好的用戶端支援。
Eclipse 中的 VSS Plugin 不如它的 SVN Plugin 好用。一個在 Windows 下用的 SVN 用戶端 TortoiseSVN 也比 VSS 的用戶端好用(VSS 只有微軟提供的一個 GUI 用戶端)。
5. 更好地與外圍工具整合。
各種各樣的外圍工具(主要是伺服器端),滿足多種需要。如果有需要,也可以自己寫外掛程式或管理指令碼,開放的架構,允許我們這樣做。
6. 方便。
一個例子:部署應用的時候,以前的做法是找出一個項目中修改過的檔案,更新到伺服器上去,現在可以在伺服器上執行 svn export 命令,把程式碼程式庫中的最新版本匯出,完成部署(也可以替換回老版本)。
7. 速度與穩定性看起來都不錯。
學習它的管理、它的工作方式,是值得的。而 VSS 是一個已經被逐漸拋棄的軟體。如果時間不是多得沒處用,那麼就把時間花在最值得花的東西上面。
最後再補充一點:
使用者、許可權管理
cvs:管理員很難清楚的知道一個項目到底有多少個使用者各使用者的許可權和密碼是什麼 只能用分組的方式系統管理使用者而且密碼和許可權還是不清晰
svn:查看、修改設定檔即可