2014年7月12日 星期六

Mercurial Bookmark 操作概念詳解





版本管理系統 Mercurial 中,有一種類似 Git 中分支的分支系統,這套系統被稱為 Bookmark。本篇將深入介紹 Bookmark 的特性與操作方式。

本文以 Mercurial 3.0 為基礎寫成,使用前建議更新一下版本哦!



Bookmark 觀念篇


就從基本概念開始吧。

需注意的是:下面提及的 push 與 pull 指令,如果沒有特別註明,一律是指沒帶參數的 hg push 與 hg pull。加了參數行為可能會改變,請小心。



規則一、命名空間唯一


Mercurial Bookmark 的命名空間只有一個。遠端與本地端之間如果有相同名稱的 bookmark,無論他們指向的目標是否相同,都表示他們是「同一個 Bookmark」。

遠端與本地端會藉由推拉操作,同步兩個倉庫中 Bookmark 所指向的位置。正因為兩者會自然同步,所以也沒有區分遠端與本地端的需要。

(至少多數時候是這樣,例外狀況見後)



規則二、pull 指令會新建,push 指令只更新


hg pull 「會抓回遠端全部 Bookmark 資訊」替本地端進行更新。如果本地端不存在同名 Bookmark,會自動在本地端新建 Bookmark

hg push 則「會送出與遠端同名之 Bookmark 的資訊」替遠端進行更新。如果遠端不存在同名 Bookmark,並不會自動在遠端新建這些 Bookmark。這將避免大量本地端書簽汙染遠端。

pull 既更新也新建,push 只更新不新建……就是這麼簡單。



規則三、自然同步遠端與本地端


當遠端與本地端具有相同的 Bookmark 時,同名的兩個 Bookmark,其指向位置會在推拉過程中自然同步。

同步的方式很簡單:
1. 如果 bookmark 在本地端的「位置」領先遠端,則 push 時會更新遠端 Bookmark 所指向的變更集,將遠端持有的 Bookmark 往開發樹的末端推進,一直推到與本地端相同的位置上。如下圖所示:

當本地端領先時的狀況,push 會更新遠端 bookmark

2. 反之如果本地端落後遠端,則 pull 時會更新本地端。讓本地端 Bookmark 往前跟進到遠端的當前位置上。如下圖所示:

當遠端領先時的狀況,pull 會更新本地 bookmark



總之,當遠端倉庫與本地端倉庫相同 bookmark 指向不同變更集時,Mercurial 會順著開發方向,隨 push pull 操作自然將兩者同步到相同的位置上。



規則四、本地端與遠端開發路線分岔時……


以上推推拉拉一切都很順利,但在真實開發過程中不會這麼理想。舉例來說,您幾乎一定會碰到「本地端與遠端 Bookmark 同時往前推進」這種狀況。

說得更具體一點,也就是「遠端與本地端的開發路線出現分岔」且「遠端與本地端的同一個 Bookmark 出現在不同的分岔上」!

而這,將使同一個 Bookmark 從邏輯上就無法再自然同步。



為了解決這種問題,當分岔發生時,hg pull 會在本地產生一個「bookmark_name@server_name」的新 Bookmark,用來標示遠端同名 bookmark 的位置。(Mercurial 只在這種時候,才會標記出遠端 Bookmark 的位置。)

Bookmark 分岔時,pull 會自動在本地端產生一個新的 bookmark@default 書籤作為提示


絕大多數時候,您可以用 merge 指令將開岔的開發路徑重新合併起來,或是暫時不管遠端在搞什麼,先開發您自己的東西,等之後再看看要不要合併。

一旦分岔路徑被重新合併,遠端的 bookmark 標記就會被現有的 Bookmark 吸收掉而自然消失,而 Bookmark 無法同步的問題也就解決了。



為防各位擔心,在此額外補充一下:hg push 無論如何都不會在遠端產生 xxx@yyy 這種東西。當 hg push 面對無法自動推進的狀況時,它僅僅只是不去更新遠端而已,您無需擔心它把遠端倉庫給搞得亂七八糟。放心 push 就對了。



指令操作,本地篇


觀念說明到此告一段落,下面看看指令怎麼下。



在本地版本庫中新增或移動 Bookmark:

hg bookmark BOOKMARK_NAME [-r 變更集]


如果您想要往開發樹的「根部」方向(反方向)移動 Bookmark,或想將 Bookmark 移往其他分岔後的開發路線時,需要下 -f 強制旗標才能移動。如下:

hg bookmark -f BOOKMARK_NAME [-r 變更集]


刪除本地端 Bookmark:

hg bookmark -d BOOKMARK_NAME


指令操作,與遠端互動


取回遠端所有的 Bookmark,並依需更新本地 Bookmark。如果本地同名 Bookmark 不存在則新建之:

hg pull

用本地端資料,依前述規則更新遠端 Bookmark:

hg push

如果想要將某本地端 bookmark 分享給大家,您必須要顯式地用 -B 參數推送它。

hg push -B BOOKMARK_NAME

上面這條指令同時也有「強制將遠端 Bookmark 更新為您本地端的狀況」的功用。無論原本遠端 Bookmark 是否存在、有沒有和本地端分岔、位置為何,在這個指令之後,全部都會與本地端的同名 bookmark 強制對齊。

換句話說,如果 BOOKMARK_NAME 在本地端不存在,本指令就是刪除遠端 BOOKMARK 的意思。

hg bookmark -d BOOKMARK_NAME  # 刪除本地 bookmark
hg push -B BOOKMARK_NAME      # 刪除遠端 bookmark


而這也是刪除遠端 bookmark 的唯一方式。



本文終了。歡迎留言補充更多操作情報。


場外加映


列出遠端有但本地端沒有的 Bookmark:

hg incoming -B

列出本地端有但遠端沒有的 Bookmark:

hg outgoing -B

1 則留言:

  1. 請教一下會有bookmark實用篇嗎?
    謝謝~

    回覆刪除

☆每日吐嘈,有益身心☆
…不過還是請手下留情別太狠啊。