彷徨えるフジワラ

年がら年中さまよってます

(特に Git 併用ユーザには是非読んでおいて欲しい) Mercurial における『ブランチ』の概念 〜 その5

今回は『名前付きブランチ』運用時に必要となる幾つかのトピックを扱う。

ちなみに、当初は『5回』の予定だったけど、あと1回加えて、全6回になる模様。

以下、各回で説明する主なトピック:

  • その1: 名前無しブランチ
  • その2: 名前付きブランチ
  • その3: ブックマーク
  • その4: 構造的ブランチ
  • その5: 名前付きブランチ運用で必要なトピック(本エントリ)
  • その6: 名前付きブランチに関するちょっと踏み込んだ話


名前付きブランチ併用時のリポジトリ連携

連携先リポジトリに対して "hg push" による履歴の反映を行う場合、原則としては:

連携先に新たに『ヘッド』を作るようなリビジョンの反映は禁止

という仕様になっているが、増加した『ブランチヘッド』のマージ責務の先送りを回避する上では、妥当な仕様と言えるだろう。

但し、2010-07-01 リリースの1.6 版より前の Mercurial では:

上記のような『構造的ブランチ』となる場合は、『名前付きブランチ』の新規作成であっても、『ヘッド』増加を理由に履歴の反映が拒否されるため、"--force" 指定を付けて "hg push" する必要があった。
また、『構造的ヘッド』が消失している『名前付きブランチ』において、新たな『構造的ヘッド』を追加するような履歴反映も、同様に "--force" 指定を必要とした:拙著『入門 Mercurial』でも、77p からのコラムで言及。

上記の場合は D3 の追加が:

上記の場合は B3 の追加が、『ヘッド』増加とみなされていた。

このようなケースにおいて、利用者に "--force" の使用を許してしまうと:

『ヘッド』が増えたせいで履歴反映できないケースは "--force" 指定すれば良い

というマインドセットができてしまい、状況に関わらず "--force" を使用してしまう危険性が出てくる。

そのため現在の Mercurial では:

  • 『ヘッド』の増加判定を、『構造的ヘッド』ではなく『ブランチヘッド』("hg heads" がデフォルトで表示する『ヘッド』)の増加で判定する
  • "--new-branch" 指定時は、『名前付きブランチ』の新規追加に由来するものに限り、『ブランチヘッド』の増加を許す

という仕様にすることで:

基本的には "--force" 付での "hg push" 禁止

という原則を徹底しやすくなっている。

名前付きブランチの閉鎖

Mercurial の『名前付きブランチ』に対して、良く言われるのが:

永続性があるのは良いが、そのために "hg branches" 表示が肥大してしまう

というもの。

しかし実のところ、2009-03-04 リリースの 1.2 版 (『入門 Mercurial』出版直後の版だ!) 時点で、明示的に『名前付きブランチ』を『閉鎖』する機能が追加されている。

『閉鎖』された『名前付きブランチ』は、"hg branches" には表示されなくなる: "--closed" 指定で『閉鎖』済みのものも表示。

『名前付きブランチ』の『閉鎖』手順は以下の通り。

  1. "hg heads ブランチ名" で、当該『名前付きブランチ』の『ブランチヘッド』を全て表示
  2. 各『ヘッド』毎に以下を実施
    1. "hg update ヘッド" により、作業領域を『ヘッド』で更新
    2. "hg commit --close-branch" により、『閉鎖』マーキングの付いたリビジョンを作成(= これが新たな『ヘッド』になる)
    3. 以上を繰り返し

『閉鎖』前の、ある『名前付きブランチ』における履歴が、以下の状態だったとすると:

『閉鎖』後には以下の状態になっている筈: "xA"/"xB"/"xC" は、それぞれ "hg commit --close-branch" 実施による、『閉鎖』マーキングの付いたリビジョン。

Mercurial は、この『名前付きブランチ』の『ブランチヘッド』を調べた上で:

全ての『ブランチヘッド』が『閉鎖』マーキングを持っているなら、この『名前付きブランチ』は『閉鎖』されている

との判断から、"hg branches" 表示から当該『名前付きブランチ』を除外する。

なお "--close-branch" により『閉鎖』された『ヘッド』は、"hg heads" においても表示されなくなるので、名前に『ブランチ』を冠してはいるものの、どちらかというと『ヘッド』の『閉鎖』を指示するオプションと捉えた方が妥当かも?

『閉鎖』済みの『ヘッド』を表示するには、"hg heads" に "--closed" を指定すれば良い点は、"hg branches" と同じ要領。

ちなみに、一旦『閉鎖』された『ヘッド』も、『閉鎖』を実施したリビジョンの子リビジョンとして、新たなリビジョンを作成することで、『閉鎖』状態を解除することができる: 『閉鎖』実施リビジョンは、『閉鎖』マーキング情報を持っている以外は、普通のリビジョンであるので、特別な準備/操作は不要。

『名前付きブランチ』の『閉鎖』判定が、先述したように:

全ての『ブランチヘッド』が『閉鎖』マーキングを持っているなら、この『名前付きブランチ』は『閉鎖』されている

であることから、これを逆手にとって:

『閉鎖』マーキングを持たない『ブランチヘッド』ができれば、その『名前付きブランチ』の『閉鎖』状態は解消される

と考えれば、至極妥当な話。

※ 以下、"その6" に続く