分布式和集中式版本控制工具-svn,git,mercurial比较分析
現象,近年來,我們對版本控制工具的關注點似乎正在改變.起初,我們主要也是唯一的目的就是對代碼進行監控,使我們能夠安全的返回到舊的版本,以便我們能夠診斷代碼中的問題.后來,我們的關注點更側重于如何使人與人之間的合作更為順暢. 這個關注點并不是要取代對代碼的監控,而是以代碼監控為基礎,并建立于其上的.現在,我們又越來越關注使用這些工具來描述代碼的變更,因此就出現了對于重寫代碼歷史命令(history rewriting command)的需求.當然,對代碼變更的描述也同樣需要建立在前兩種關注點之上.
我們可以把版本控制工具的應用分為六個層次:
0. 沒有版本控制
完全沒有版本控制的解決方案,或者就使用一個共享的文件系統,并對其做定期的備份.一個開發人員,或者最多幾個開發人員在沒有工具的情況下共享代碼,其面臨的風險可想而知:
- 在任何時刻,代碼可能都是不兼容的.
- 代碼可能會由于開發人員的錯誤面丟失.
- 如果開發人員想要改寫覆蓋他人所做的修改,那再容易不過了.
1. 初步的探索
- 開發人員擁有了網絡上的工作空間,他們無法在線下工作.
- 運行一次代碼構建也許就意味著有時間可以去好好吃一頓了.
- 重構即使能夠進行,也慢的要死.
- checkout代碼可能需要一整夜.
- checkin代碼也很慢.
- 沒有原子提交.
- Branching和Tagging操作的代價昂貴.
- 個人或是本地建立branch就意味著再次的checkout.
- 集中式的,而不是公布式的.
- 合并點的跟蹤很慢或是根本無法使用.
- 這時的工具還沒有辦法理解重命名的合并.
- 代碼庫有時會崩潰,需要較高的專家/開發人員比例,如1:10.
這時的工具有了基本的版本控制功能,如checkout,版本記錄和鎖文件.通常這就意味著開發人員在同一份代碼上工作,而代碼的同步就會依賴于每個人代碼文件的鎖狀態.這種工具在擴展和長期工作上都會有問題.對資源的重命名難到幾乎不可能完成.Branching和Tagging操作則會需要同時操作三份代碼的權限,而且可能還需要一個宰好的或者兩柱香.如, VSS.
2. 笨拙
- 開發人員有了本地的拷貝,并且可以在線下工作.
- 本地的文件系統意味著構建的速度大大提升.
- 重構的時間只夠喝杯茶了.
- checkout的速度已經非常快了.
- checkin也許還是慢一點.
- 仍然沒有原子提交.
- Branching和Tagging代價仍然昂貴.
- 集中式的,不是分布式的.
- 合并點的跟蹤很慢或是根本無法使用.
- 沒有辦法合并重命名文件,需要在提交前使用一些擴展的跟進沖突解決機制.
- 代碼庫有時會崩潰,專家/開發人員比例已經得到優化,如1:20.
如CVS和TFS.
3. 基本成型
- 開發人員擁有本地拷貝并且可以在線下工作.
- 在本地文件系統上可以進行快速的構建.
- 可以快速的重構.
- checkout和checkin的速度都會非常的快.
- 終于有了原子提交.
- 輕量級的Branching和Tagging操作.
- 基本的合并操作.
- 個人/本地的branching操作仍然需要再次checkout.
- 因為仍然是集中式的,而不是分布式的.
- 基本的合并點追蹤.
- 沒有辦法合并重命名文件,需要在提交前使用一些擴展的跟進沖突解決機制.
- 代碼庫有時會崩潰,專家/開發人員比例已經很低,如1:100.
如Subversion.
4. 有效并且可靠
- 開發人員擁有本地拷貝并且可以在線下工作.
- 在本地文件系統上可以進行快速的構建.
- 可以快速的重構.
- checkout和checkin的速度都會非常的快.
- 無操作的代碼同步和更新非常的快速.
- 終于有了原子提交.
- 輕量級的Branching和Tagging操作.
- 高級的Branching和合并操作.
- 個人/本地的branching操作仍然需要再次checkout
- 因為仍然是集中式的,而不是分布式的.
- 完善的合并點追蹤.
- 合并重命名文件只能通過配置好的branch映射來實現,否則就需要在提交前進行修訂.
- 代碼庫很少會崩潰,專家/開發人員比例非常低,如1:1000.
如Perforce.
5. 高速,無形,高度可用
- 開發人員擁有本地拷貝并且可以在線下工作.
- 在本地文件系統上可以進行快速的構建.
- 可以快速的重構.
- checkout和checkin的速度都會非常的快.
- 無操作的代碼同步和更新非常的快速.
- 終于有了原子提交.
- 輕量級的Branching和Tagging操作.
- 高級的Branching和合并操作.
- 非常高效的個人/本地branching操作.
- 分布式的,而不是集中式的.
- 完善的合并點追蹤.
- 無縫合并重命名文件,無需任何配置.
- 代碼庫很少會崩潰,專家/開發人員比例幾乎為零,如1:10000.
如Git和Mercurial.
通過前面版本控制工具的演化過程,我們基本上可以看到分布式工具的特點和優勢了.相對于以往的客戶-服務器端的集中式系統,它所采用的是一種P2P的方式.客戶端不再需要從一個單一的中央代碼庫同步代碼,每一個端點的代碼的拷貝都是真正的代碼庫.分布式的版本控制系統是通過端點之間交換補丁(patch)的方式來同步代碼的,而這種方式就決定了分布式系統與集中式系統的幾個重要的區別:
- 默認情況下,沒有標準的代碼庫參照;只有工作代碼的拷貝.
- 由于不需要與中央服務器進行通信,因此一般的操作(如提交,查看歷史和還原修改等)的執行速度非常快.只有在向其它端點push代碼更改或者從其它端點pull代碼更改的時候才會需要進行通信.
- 每一份代碼拷貝都可以作為代碼庫及其更改歷史的一份遠程備份,這就為數據丟失提供了天然的保護.
- 鼓勵測試性的branch - 創建或者銷毀branch的操作簡單而且快速.
- 同伴之間的合作變得非常容易
現在的項目用的是Subversion做版本控制,但是我們自己用的是git-svn,這里主要通過這兩種有代表性的工具來比較一下集中式和分布式工具的優勢.
Subversion提倡單一的中央代碼庫模型,不提倡大規模的branching.在一個使用持續集成的環境中,其實也就是我們每天工作的環境,這個模型是非常合適的.這也是Subversion為什么這么流行,應用范圍這么廣的原因之一.
雖然分布式的系統使你擁有足夠的靈活性來自己安排自己的工作流程,但是其實大多數人的工作模式仍然是使用持續集成,這也就意味著需要一條可以共享的代碼庫主線.現在的版本控制系統已經有了神奇的合并工具,但這些合并仍然只限于文本.所以對于語義上的一致,仍然需要持續集成來保證.結果就是即使一個團隊在使用分布式的版本控制系統,他們仍然會需要一個主版本庫.
即使如此,分布式系統仍擁有一些SVN無法提供的體驗.
- 在分布式管理系統中,你可以在自己本地磁盤上擁有代碼庫的完整拷貝,對代碼庫的操作不需要通過網絡向中央服務器進行請求,因此速度會非常的快.特別是你在進行查看日志,與舊版本代碼進行比較或者其它需要完整代碼庫的操作時,這種速度上的改善會非常明顯.對于集中式的系統,在局域網內你也許只會覺得有點慢,但如果當你工作在一個分布式的項目中,你的代碼庫在另一個大洲的時候,這就會是非常大的問題了.
- 如果你經常在四處奔走,無法隨時與代碼庫建立網絡連接,那么一個分布式的管理系統會使你可以隨時與代碼庫一起工作.你可以隨時隨地提交你的工作,瀏覽歷史,并且在比較版本間的差異.
- 還有一項體驗也許并不能說是一個工具問題,而更多的是一個社會問題.分布式版本控制工具鼓勵快速的branching和試驗.在SVN中,你當然也可以進行branching操作,但是你所做的操作對于其它在這個代碼庫上工作的人員也是可見的, 這也許并不是什么大問題,但確實會降低人們進行一些實驗性工作的欲望.分布式系統則會鼓勵你為工作代碼進行記錄:你可以向你的本地代碼庫提交未完成的修改,甚至是無法通過測試和無法編譯的代碼.你同樣可以在SVN中進行這些操作,但是在公共空間中創建這些branches總是讓人望而卻步.
在某種特定情況下,SVN也有其相應的優勢,如果你需要對版本控制系統難以合并的二進制文件(如word文檔或者ppt)進行管理的話,你就應該回退到獨占式checkout的鎖機制下,這就需要一個集中式的系統.另外,SVN更容易上手:你有一個代碼庫,所有的更改都指向這個代碼庫,如果你知道如何創建,提交以及checkout,那你就可以開始使用它了,而像branching,更新這些操作在使用過程中自然也就慢慢熟悉了.SVN擁有一些非常好用的客戶端軟件,而且幾乎所有的主流IDE都有與SVN集成的插件,這些都能夠為你使用SVN提供很大的幫助.
Git則增加了復雜性,似乎總是有兩種模式來進行操作,checkout和clone, commit和push...... 你得知道哪些命令是針對本地進行操作的,哪些命令是對服務器或者是主代碼庫進行操作的. 實際上,Git的命令和思維模式與其它的版本控制系統是有所不同的.Bulter Cole曾這樣形容Git:"它是一個神奇的功能強大的東西,它幾乎可以做任何你讓它做的事情,只有你知道如何讓它做".Git的反對者也會抱怨Git缺少可發現性,你很難從它的表面設計推斷出它的行為.而Git的支持者則認為這只是因為Git使用了不同于其它系統的思維模式,你需要先忘掉以前那些關于版本控制系統的知識才能更好的來欣賞Git.無論如何,Git對于那些喜歡研究事物內部工作機制的人來說,還是非常有吸引力的.
通常來講,Git相比Mercurial在處理branching方面表現更好,尤其是用于試驗和檢查點的短期branch.Mercurial提倡是另一種機制,例如快速的clone一份代碼庫或者是使用補丁,但是Git的branching模式更為簡單好用.Mercurial在處理大型二進制文件時同樣有問題.通常的建議是使用SVN來管理二進制文件,如果你只有很少的二進制文件需要管理,不值得建立單獨的管理機制的話,Mercurial將就著也能處理.
此外Git之所以能在網絡上引起如此多的共鳴,有一個很大的原因是Git對于開源項目來說是完善的選擇.你可以新建一個項目分支,向你自己的項目分支提交修改,然后讓項目維護人員將你的修改pull過去.有了Git,這一切就變得如此的方便和自然.即使你沒有向項目提交修改的權限,你也可以在線上建立你自己的代碼庫,將你自己的補丁發布出來,任何喜歡你補丁的人都可以將它們pull到他們自己的代碼庫中,當然也包括項目維護人員.
Git有一個被稱為"staging area"的區域.在你向代碼庫提交之間, 你可以在這個中間區域中構建你的提交.更為重要的是,你可以只提交部分的修改,而不是將所有修改的文件都進行提交.你甚至可以只提交一個文件中修改的一部分.
Git非常的靈活,非常的TIMTOWTDI(There is more than one way to do it). 你可以使用任何你喜歡的工作流程,Git都會對其提供支持.
當前主要的工作流程有以下幾種:
1. SVN形式
集中式的工作流程,這也是一種非常普遍的Git的工作流程.如果在你上一次fetch代碼之后有其他人進行了提交,那么Git將不允許你向主代碼庫中push你的代碼.
2. 集成管理形式
在這個工作流程中有一個集成管理人員,他向"blessed"代碼庫進行提交,其他開發人員從這個代碼庫clone代碼,在他們自己的代碼庫中push修改,并讓集成管理人員pull他們的修改.這其實就是大多數開源項目和GitHub所經常使用的開發模式.
3. 獨裁者和中尉形式
對于更大規模的項目來說,你可以將開發人員的開發模式設置成類似于Linux內核的開發模式.某些人會負責項目的某個特定的子系統(中尉),并且將所有關于這個子系統的修改都進行合并.另外會有一個集成者(獨裁者)可能從他/她的中尉那里pull代碼的修改,并將"blessed"代碼庫進行提交.而所有人都可以從"blessed"代碼庫進行代碼的拷貝.
再次強調,Git對于工作流程的支持非常的靈活,你可以根據自己的需要來匹配,混合,選擇這些工作流程.
我們再來看看相對于SVN,Git還有哪些優點吧:
據說目前Git不支持代碼庫的部分checkout/clone,但是正在開發中,而且已經有submodule方面的支持.SVN則可以根據需要只從代碼庫中checkout某個子文件夾.SVN的版本號更短并且可以預知,而Git的版本號則是40位的16進制數字串.而Git在Branch方面的處理應該是有很大的優勢,但是由于我目前為止幾乎沒有使用過branch,所以這一部分還沒有深刻的體會.
轉自:http://www.uml.org.cn/pzgl/201207264.asp
總結
以上是生活随笔為你收集整理的分布式和集中式版本控制工具-svn,git,mercurial比较分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国农业大学2020计算机院线,2020
- 下一篇: 【工具推荐】在线latex公式编辑器(可