(特に Git 併用ユーザには是非読んでおいて欲しい) Mercurial における『ブランチ』の概念 〜 その4
今回は "topological branch" の話。
以前は原語の "topological branch" を正確に直訳した『位相(幾何学)的ブランチ』という呼称を用いていたが、現在はオンラインヘルプも含めて『構造的ブランチ』という呼称を用いるようにしているので、旧来の呼称に馴染んでいる人は要注意。
以下、各回で説明する主なトピック:
- その1: 名前無しブランチ
- その2: 名前付きブランチ
- その3: ブックマーク
- その4: 構造的ブランチ(本エントリ)
- その5: 名前付きブランチ運用で必要なトピック
- その6: 名前付きブランチに関するちょっと踏み込んだ話
構造的ブランチ
再度の確認となるが、リビジョン X が『名前無しブランチ』となる条件は以下の通り。
- X の親リビジョン P が、P と同一の『名前付きブランチ』内に、X 以外の子リビジョンを最低1つ持つ
- リビジョン X と P が、同一『名前付きブランチ』に属する
この条件から、『名前付きブランチ』に関するものを取り除いて:
- X の親リビジョン P が、X の他に子リビジョンを持つ
という、その1時点での定義だけで『枝分かれ』を判定したものを、『構造的ブランチ』 (topological branch) と呼ぶ。一般的な感覚で言えば、『枝分かれ』=『構造的ブランチ』であろう。
『名前無しブランチ』の作成は、新たな『構造的ブランチ』の作成と等価であるが:
『名前付きブランチ』の作成は、必ずしも新規の『構造的ブランチ』を作成するとは限らない場合がある。
例えば、単一『ヘッド』な "default" ブランチの最新成果 D2 の上に、『名前付きブランチ』として "BRANCH" を作成した場合:
この時点では履歴が直線であることから、『名前付きブランチ』"BRANCH" の作成は、新たな『構造的ブランチ』の作成とはならないのだ。
ここで:
"default" 側で開発が継続されているのであれば、早晩 "default" 側にもリビジョンが追加される筈
と考えるならば、想定上の(未来の)履歴ツリーは以下のようになるので、"BRANCH" は『枝分かれ』していると考えても差し支えない。
『名前付きブランチ』の名称における『ブランチ』は、将来的な『枝分かれ』の可能性に期待(笑)しての『ブランチ』と言える: この点は Git における『ブランチ』も同様の筈。
但し、単に『なし崩し的に』そういう呼称を使うことになった可能性も高く、その2でも書いたように、『名前付きブランチ』のことを『リビジョングループ』と呼んでいれば、もっと概念体系的には簡単になったかもしれない。
ブランチヘッドと構造的ヘッド
"hg heads
" のデフォルトの挙動で表示されるリビジョンは:
同一の『名前付きブランチ』に属する子リビジョンが無いリビジョン
上記のように定義されるが、Mercurial ではこの定義に該当するリビジョンを『ブランチヘッド』と呼んでいる。
『ブランチヘッド』の条件から『名前付きブランチ』に関する条件を取り除いた:
子リビジョンを全く持たないリビジョン
その1時点での簡略化した『ヘッド』定義と同じ、上記の定義に該当するリビジョンは『構造的ヘッド』と呼ばれている: 『名前無しブランチ』〜『構造的ブランチ』の対比も参照。
"hg heads
" のデフォルト挙動が、『構造的ヘッド』では無く『ブランチヘッド』の表示なのには理由がある。
例えば、先述した以下の状態において:
『構造的ヘッド』(= 子リビジョンを持たない)か否かで判定した場合、『名前付きブランチ』 "BRANCH" の最新リビジョン B1 のみが『ヘッド』と判定され、"default" からは『ヘッド』が消失してしまう: D2 は『構造的ヘッド』とはみなされない。
しかし、以下の図のような今後の履歴追加を想定した場合:
"default" 内には子リビジョンを持たない D2 も、(潜在的な)『ヘッド』とみなした方が(利用者の感覚的には)良かろう、というわけだ。
上記の例は、『名前付きブランチ』の作成による『枝分かれ』元(= "default")における『ヘッド』消失であったが、これとは逆に、『名前付きブランチ』間でのマージが発生した際も:
『構造的ヘッド』か否かで判定した場合、B3 リビジョンが作成されるまでは、マージ元となった『名前付きブランチ』 "BRANCH" 側において『ヘッド』が消失してしまうことになる。
例えば、『名前付きブランチ』内に複数の『ヘッド』があり、且つそれらが他の『名前付きブランチ』の『枝分かれ』元になるなどして、『構造的ヘッド』ではなくなっているような状況では、単に『名前付きブランチ』の最新リビジョンに移動して作業を継続すればよい、というわけにはいかない: 各『ヘッド』をきちんと把握した上で、マージ要否等を判断する必要がある。
『ヘッド消失』の何が困るかというと、上記のような状況が容易に検出できなくなってしまうところだ。
"hg heads
" のデフォルト挙動が『ブランチヘッド』か否かの判定であることにより、『名前付きブランチ』内には『構造的ヘッド』が無くなってしまうようなケースでも、『ヘッド』の状況を正確に把握することが可能になる。
なお『常にこの挙動が妥当か?』というと、必ずしもそうとは限らないので、"hg heads
" コマンドは、純粋に『構造的ヘッド』 のみを表示するための "--topo
" ("topo"logical) というオプションを持っている。
※ 以下、"その5" に続く