Mercurial: "A tour of Mercurial: merging work" を読む
Tagged:  •    •  

今回は "3. A tour of Mercurial: merging work" を読みます。

3.1 Merging streams of work

普段 CVS のような中央集約的な構成管理ツールを使用していると、 「マージが基本的な作業の一つ」と聞いて、 「ブランチのマージ」のような作業を想像して、 面倒な気がするかもしれません。

しかし、 実は「マージが基本的な作業の一つ」であるのは、 何も分散リポジトリ形式の構成管理ツールの専売特許ではないのです。

例えば CVS の場合、 あなたの作業が一段落してコミットしようとした際に、 既に誰かが同じファイルに対してコミット済みであれば、 cvs update でその変更内容を作業領域に取り込んで、 衝突(conflict)を解消してから改めてコミットします。 一定数以上の開発者が平行して作業している場合、 この手の作業は珍しくは無いでしょう。

この「変更内容を取り込んで衝突を解消」する作業そのものが、 「マージ」なのだとしたら、 実は「マージ」も案外たいしたこと無い気がしませんか?

3.1.1 Head changesets

Mercurial における変更履歴がツリー状になることを考えれば、 計算機科学用語的には、 "head" よりも "leaf" と言った方がピンと来るかもしれません。

3.1.2 Performing the merge

実際のところ、 同じファイルへの変更が(patch コマンド的に) 干渉しない場合、 Mercurial でのマージは拍子抜けするほど簡単です。

hg merge して、 hg status なり hg diff で内容を確認したら、 後はコミットするだけです。

仮に、同じファイルへの変更が衝突(conflict)した場合でも、 3-way diff による衝突の解消をするだけですから、 やることは CVS でのコミット前確認作業と変わりません。

3.1.3 Committing the results of the merge

構成管理上で厳密に言うなら、 コミットしてやっと「マージ」が完了します。

3.2 Merging conflicting changes

CVS や Subversion では、 衝突が検知された場合のマージ実施は merge コマンド (diff3 の方が通りが良いのでしょうか?) が固定的に使用されますが、 Mercurial では設定ファイルへの記述 (もしくは HGMERGE 環境の変数) を行うことで、 任意のツールでマージを行うことができます。

3.2.1 Using a graphical merge tool

O'Sullivan 氏は kdiff3 がお気に入りのようですが、 個人的には、 ファイル一つ一つごとに順に衝突解消をするよりは、 一旦全てのファイルで diff3 形式のマージをしておいて、 全体の具合を眺めながら衝突を解消する方が好みです。 もしかすると CVS や Subversion の流儀に毒されているのかもしれませんが。

3.2.2 A worked example

この節は、所謂「再現映像」です。

3.3 Simplifying the pull-merge-commit sequence

恥ずかしながら、 この節を読むまで fetch イクステンションの存在に気付きませんでした。

ただ、ソースをぱっと見た限りでは、 増えた head のブランチ性の確認はしていないような気がするので、 構成管理方針(ブランチ利用の有無)次第では、 使用前にちょっと検証してみる必要があるかもしれません。


使い始めは「しょっちゅうマージするなんて面倒」という印象から、 分散リポジトリ形式の構成管理ツールが面倒に見えるかもしれませんが、 同じファイル・同じ場所で余程強烈な衝突を起こさない限りは、 cvs update して衝突の有無を確認するのと大差ないですから、 暫くすると「マージ」 そのものに対する抵抗が無くなっていることに気付くのではないでしょうか。


"Distributed revision control with Mercurial" 関連エントリの一覧は、BOSBook(Bryan O’Sullivan Book)タグで参照できます。