卷1:第12章 Mercurial

2018-02-24 15:55 更新

作者:Dirkjan Ochtman

譯者:謝路云

狀態(tài):完成

原文鏈接:http://www.aosabook.org/en/mercurial.html

Mercurial是一個現(xiàn)代分布式版本控制系統(tǒng)(VCS),主要由Python語言編寫,以及一小部分C代碼,以提高性能。在本章中,我會討論Mercurial設計上的一些關于算法和數(shù)據(jù)結構的決策。首先,請允許我簡短的回顧一下版本控制系統(tǒng)的歷史,介紹一些必要的背景知識。

12.1.版本控制簡史

雖然這一章的主要內(nèi)容關于Mercurial的體系結構,但其中的許多思想和其他版本控制系統(tǒng)是共通的。為了更好的討論,我想先說明一些存在于不同版本控制系統(tǒng)中的概念和行為。為了恰當?shù)恼f明這一切,我還將簡單的介紹一下這個領域的歷史。

版本控制系統(tǒng)的發(fā)明是為了幫助軟件系統(tǒng)的開發(fā)人員并行的工作,而不必相互傳遞文件的拷貝并人工的記錄文件的修改歷史。我們可以將軟件的源代碼文件擴展到任意文件樹。版本控制的主要功能之一就是傳遞樹的變化。工作流程的基本循環(huán)是這樣的:

  1. 從其他人處獲取最新的文件樹
  2. 對這個版本的樹進行一系列修改
  3. 發(fā)布并使其他人可以獲得這些修改

第一個動作,也就是獲取一份本地的文件樹,被稱為“檢出”(checkout)。我們獲取和發(fā)布所有修改的地方叫做“版本庫”(repository),而檢出得到的目錄則被稱為“工作目錄”、“工作樹”或是“工作拷貝”。用版本庫中的最新文件更新工作拷貝的動作就叫做“更新”(update)。有時候這還會涉及到“合并”(merge),也就是組合不同用戶對同一個文件作出的修改。diff命令使我們能夠查看樹或文件在兩個版本之間的變化,它最常見的用途是檢查你的工作目錄中的本地(未發(fā)布的)修改。修改的發(fā)布是通過一個“提交”(commit)命令完成的,它會將工作目錄的改變保存到版本庫中去。

12.1.1.集中式版本控制

史上第一個版本控制系統(tǒng)叫做“源代碼控制系統(tǒng)”(Source Code Control System, SCCS),出現(xiàn)于1975年。它的主要功能是將差異保存在文件中,這比保存一個文件的多個版本的完整拷貝更經(jīng)濟,但它無法將這些差異傳播給其他人。它的繼任是1982年出現(xiàn)的“修訂控制系統(tǒng)”(Revsion Control System, RCS)。RCS是SCCS更加先進并且免費的替代品(它至今仍在GNU項目的維護之下)。

RCS之后是“并行版本系統(tǒng)”(Concurrent Versioning System, CVS),發(fā)布于1986年。它最初是一組批量處理RCS修訂文件的腳本。CVS最大的創(chuàng)新是實現(xiàn)了多個用戶同時編輯相同的文件并在最后合并所有的修改(并行編輯)的模式。這也產(chǎn)生了“編輯沖突”的概念。開發(fā)者提交的新版本文件必須基于版本庫的最新版本之上。如果版本庫和我的工作目錄都對文件作出了修改,那么我必須解決這些修改所產(chǎn)生的所有沖突(修改了同一行的情況)。

CVS也開創(chuàng)了“分支”(branch)以及“標簽”(tag)的概念。分支使得開發(fā)者能夠并行的工作在不同的任務之上,標簽則可以用來標記版本庫的一個快照以便引用。雖然CVS一開始是通過將版本庫放在共享文件系統(tǒng)上來傳遞差異的,但隨后CVS實現(xiàn)了C/S架構以適應大型網(wǎng)絡中的應用(例如因特網(wǎng))。

在2000年,三位開發(fā)者為了糾正CVS中的設計缺陷一同完成了一個新的版本控制系統(tǒng),叫做Subversion。Subversion最主要的特點將工作樹作為一個整體對待。也就是說,每個修訂所作出的變更都應該具有原子性、一致性、隔離性和持久性。Subversion能夠在工作目錄中記錄工作拷貝的檢出版本,這樣常用的diff操作(比較本地的工作樹和檢出的版本)就能更快的在本地進行。

Subversion的一個有趣的概念是標簽和分支都是項目樹的一部分。一個Subversion項目通常分為三個部分:tags、branchestrunk。事實證明這種設計對于不熟悉版本控制系統(tǒng)的用戶非常直觀,盡管這種設計的天然靈活性也為各種版本庫轉換工具帶來了大量問題,大部分是因為在其他版本控制系統(tǒng)中,tagsbranches有更加結構化的表示方法。

以上提到的都是“集中式”的版本控制系統(tǒng)。也就是說,盡管它們知道如何交換變更(從CVS開始),但是它們?nèi)匀灰蕾囉诹硗庖慌_計算機來記錄版本庫的歷史。而“分布式”的版本控制系統(tǒng)則會在存在工作拷貝的每臺計算機上都保存版本庫的完整或是部分歷史。

12.1.2.分布式版本控制

盡管Subversion相比CVS有了明顯的進步,但它仍有許多缺點。首先,在所有的集中式版本控制系統(tǒng)中,由于版本庫的歷史集中在同一個地方,變更集的提交和發(fā)布實際上是一回事,這也意味著在沒有網(wǎng)絡的情況下是無法提交變更的。其次,在集中式版本控制系統(tǒng)中,訪問版本庫總是需要一次或者多次的網(wǎng)絡請求,比分布式版本控制系統(tǒng)中的本地訪問要慢的多。再次,以上提到的所有版本控制系統(tǒng)都不擅長于記錄合并(隨著系統(tǒng)的改進,有些能夠支持)。在有許多人并行工作的大型團隊之中,版本控制系統(tǒng)必須能夠記錄每個新的修訂版本都包含了哪些變更,這樣才能保證不丟失任何工作,并且后續(xù)的合并也能使用這些信息。第四,傳統(tǒng)版本控制系統(tǒng)的集中特性有時非常別扭,它強迫你只能在一個地方進行集成。分布式版本控制的提倡者認為,使用分布式系統(tǒng)的團隊的組織更加自然,開發(fā)者們能夠根據(jù)項目的需要在任何推送和集成變更。

為了滿足這些需求,已經(jīng)出現(xiàn)了許多新的工具。我(從開源世界的角度)認為,2011年中最重要的三個當屬Git、Mercurial和Bazaar。Git和Mercurial都始于2005年,當時Linux內(nèi)核的開發(fā)者們決定不再繼續(xù)使用專有系統(tǒng)BitKeeper。兩者都是由Linux內(nèi)核開發(fā)者發(fā)起的(分別是Linus Torvalds和Matt Mackall),以滿足對能夠處理上萬文件的成百上千個變更集進行管理的版本控制系統(tǒng)的需求。Matt和Linus都深受另一個版本控制系統(tǒng)Monotone的影響。同一時期的Bazaar的開發(fā)則相對獨立,但在被Canonical采納為所有項目的版本控制系統(tǒng)之后也得到了很廣泛的使用。

構建一個分布式的版本控制系統(tǒng)顯然會遇到許多挑戰(zhàn),其中一部分是所有分布式系統(tǒng)所固有的。例如,在集中式系統(tǒng)中源代碼控制服務器總是保存著一份統(tǒng)一的版本歷史,但在分布式系統(tǒng)中是不存在統(tǒng)一的版本歷史的。分布式系統(tǒng)允許并行的提交變更,這使得在任何版本庫中按照時間將修訂歷史排序都是不可能的。

幾乎所有的系統(tǒng)都采用了有向無環(huán)圖(DAG)而非線性的變更集方式組織來解決這個問題( 圖12.1 )。也就是說,新提交的變更是其基礎版本的子版本,且不可能有任何版本的基礎是自己或是自己的子嗣。在這個方案中,我們有三種特殊類型的修訂版本: 沒有父版本的“根版本”(root revision),一個版本庫可以有多個根版本),有一個以上父版本的“合并版本”(merge revision),和沒有子版本“頭版本”(head revision)。每個版本庫都是從一個空的根版本開始不斷產(chǎn)生一系列變更集,最后得到一個或者多個頭版本。當兩個用戶分別獨立的提交了變更且其中一個人希望從另一個人那里拉?。╬ull)變更集時,他必須明確的將另一個人的變更合并從而得到一個新的版本,這個版本的提交將得到一個合并版本。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號