理解 Mercurial

理解 Mercurial

Mercurial 的分佈式協同模式,對於新手而言是混亂的, 本文試圖澄清一些基本概念,至於 hg 的使用,請參考:Mercurial教程

1. 倉庫(Repository)中有什麼?

Mercurial倉庫(Repository) 包含工作目錄(Working Directory) 和版本倉庫(.hg目錄)

版本倉庫(存在於.hg隱藏目錄中)包含了完整的項目歷史. 不同與其它配置管理系統,那些集中式版本管理系統,只有一個包含所有版本歷史的中央倉庫,而每人本地的工作目錄則僅包含當前最新版本. 這將有利於開發者進行並行協作.

工作目錄包含的是項目文件當供給編輯的在某個時間點的狀態(比如上圖中的rev 2). Mercurial中的標籤(Tag)和 忽略文件聲明(.hgignore文件),也被版本控制,所以他們也包括在上圖中.

Mercurial中的每個版本都有其 父輩版本,比如上圖中rev 2的父輩是rev 1,而工作目錄的父輩是rev 2.

2. 提交變更(Commit Changes)

提交(Commit)操作後,工作目錄的父輩版本就成了剛剛提交的新變更集(Changeset)(也稱爲新 "版本(Revision)"):

上圖中的rev 4rev 2的一個分支, 現在rev 4是工作目錄的父輩.

3. 版本,變更集,頭部,頂部

Mercurial中多個文件的相關修改稱爲變更集(ChangeSet), 每個版本(Revision)對應一個變更集。 每個變更集會分配一個遞增的整數 版本號。在分佈式開發過程中, 各個用戶的版本號會產生衝突. 因此每個變更及也會被分配一個全局唯一的變更集ID. 變更集ID是四十位的16進制數字, 也可以略寫成足夠明確的"e38487"形式.

在版本歷史的任何一點,都可以進行分支與合併(Merge).而每一個未合併的分支,實際都創建了版本歷史的一個新頭部(Head).

上圖中的rev 5rev 6 都是頭部。 版本號最大的頭部被稱爲頂部(Tip), 如上圖中的 rev 6.rev 4兩個父輩(rev 2rev 3),它是個合併變更集.

4. 克隆,變更,合併,拉和更新

假設用戶Alice有如下所示的倉庫:

Bob 在本地克隆(Clone)了這個倉庫, 得到了Alice的版本倉庫的一個完整、獨立的本地副本. 並通過檢出操作,獲得了最新頂部版本.

Bob提交(Commit)兩個修改ef(在他本地倉庫):

同時,Alice也修改她的版本g, 因此她的倉庫與Bob的不同了, 也就是說,她創建了一個分支(Branch):

Bob使用pulls(拉取)操作將Alice的倉庫變更到本地. 這個操作將Alice的所有修改集更新到Bob的版本倉庫中 (這個例子中只有一個修改集g).

需要注意的是,這個操作並 沒有 更改Bob的工作目錄:

因爲Alice's g 版本是最新的頭部, 因此此版本也是 tip(頂部).

Bob隨後進行了合併(Merge)操作, 將其本地修改(f)與倉庫中的tip進行合併. 這時, 他的工作目錄具有兩個父輩(f和g):

查看並確認操作合併成功後, Bob 提交合並結果,得到了一個新的合併變更集h在他的本地倉庫中:

現在,如果Alice pulls 從 Bob的倉庫, 她會得到Bob的變更e,fh:

注意! 當前 Alice 的工作目錄並沒有因 pull(拉取)操作而改變. 她必須使用更新(Update)操作來同步版本倉庫到合併變更集h. 這將改變她版本倉庫的父輩到h,並將工作目錄中的文件更新成h版本的.

Alice和Bob完全同步了.

5. 分佈式系統

Mercurial是一個完全的分佈式系統, 因此沒有所謂的集中式倉庫概念. 這也意味着用戶可以自由的定義協同工作的組織結構

在一個集中式版本管理系統中提交實驗性的修改可能會造成較大的負面影響, 但對於Mercurial之類的DVCS來說, 可以肆意的進行試驗性操作, 大不了刪除本地工作目錄,因爲在別的地方還有若干完整的。

6. 什麼是Mercurial不能做的

SVN/CVS用戶會將多個相關的項目放在同一個倉庫裏. 但是這真的不應該在Hg 中這麼做,因爲在Hg 中你只能檢出整個倉庫,而不是其中的某個目錄.

如果確實想要將多個項目放在同一個倉庫中, 可以使用1.3版本以後的子倉庫 功能或者更老版本的 ForestExtension 將不同項目的倉庫,嵌套成一個大倉庫.

關於Mercurial的入門操作, 請參閱 Mercurial教程.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章