Mercurial の Automatic Pooled Storage for Clones
本エントリでは、Mercurial 3.5 から導入された "Automatic Pooled Storage for Clone" について説明します。
なお、この機能の開発を主導した、"Mozilla の中の人" こと Gregory Szorc 氏自身も、"My Contributions to Mercurial 3.5" と題したブログエントリで、この機能について言及しています。
share 機能の概要
同一のプロジェクトにおいて、複数の作業を平行して行う場合に、hg clone
でリポジトリを複製し、複製先で作業することもあるでしょう。
$ hg clone src cloned1 $ hg clone src cloned2 $ hg clone src cloned3
しかし、hg clone
での複製による運用は、履歴情報(図中の色つき矩形部分)が各リポジトリに散在してしまうことから、場合によっては以下の様な点が気になるかもしれません:
前者の問題に関しては、ハードリンクが使用できる環境で、且つ同一ファイルシステム上での hg clone
であれば、履歴情報の大部分はハードリンクを使って共有されるのですが、それであっても、大量のファイルや履歴を扱う大規模プロジェクトの場合は、無視できないケースが多いでしょうねぇ。
ここで、hg clone
コマンドの代わりに、標準同梱される share エクステンションが提供する hg share
コマンドを使うと:
$ hg share src cloned1 $ hg share src cloned2 $ hg share src cloned3
複製先リポジトリは、複製元 src の履歴情報を参照しつつ、作業領域での作業は、独立して実施できるようになります。
この状態で複製先で追加された新規リビジョンは、全て複製元リポジトリである src の履歴管理領域に書き込まれます。履歴情報がこのように集約されることにより、先述した問題は解消されます。
また、通常のリポジトリ複製は、多数の履歴情報ファイルの複製を伴うため、(ハードリンクを使う場合であっても)非常にコストが高いのですが、履歴管理領域を共有する場合は、複製先の管理領域に、履歴情報参照先を書き込むだけなので、非常に高速に処理を終えることができます。
ちなみに、上記の構成例において、 cloned1 の作業領域がリビジョン R を参照している状態で、cloned2 等でリビジョン R を破棄するような履歴改変操作 (e.g. rebase や histedit、strip 等) を実施すると、cloned1 は未知のリビジョンを参照することになってしまいます。
また、「直前の操作1つ分」しか取り消しのできない hg rollback
は、「履歴管理領域あたり」での「直前の操作1つ分」になりますから、通常構成時の使い勝手との違いに、戸惑うことになるかもしれません。
一見しただけだと、良い事尽くめに見える share エクステンションが、現状ではデフォルトで無効化されているのは、こういった点への理解が無いまま使用した場合に、ユーザが混乱してしまうことへの配慮と思われます (上記のような留意点に関しては、 hg help -v share
でも言及されています)。
リモートリポジトリ連携での share 利用
hg share
コマンドに指定する複製元リポジトリは、ローカルホスト上のものでなければなりません。
そのため、リモートホスト上のリポジトリ src と連携するケースで:
$ hg clone URL-of-src cloned1 $ hg clone URL-of-src cloned2 $ hg clone URL-of-src cloned3
履歴情報を集約するためには、一工夫する必要があります。最初に「共有用途」専用のリポジトリを hg clone
した上で、そこから hg share
を実行するのです。
$ hg clone URL-of-src shared $ hg share shared cloned1 $ hg share shared cloned2 $ hg share shared cloned3
但し、この運用方法を採用した場合、作業用リポジトリの複製の際には、以下の様な手順を踏む必要があります。
最初にルールを決めた上で、きちんと運用できれば良いのですが、多少なりとも手間の掛かる運用は、確認忘れやうっかりミスで、次第に徹底されなくなってしまう可能性が高いと言えます。
Automatic Pooled Storage for Clones
Mercurial 3.5 で導入された "Automatic Pooled Storage for Clones" により、share エクステンション有効時の hg clone
の挙動は、以下のようになります。
[share] pool
設定で指定されるディレクトリ直下を確認- 複製元 src に対応する共有用リポジトリ (以下 "shared") が無ければ新規作成
- 複製元 src から shared に履歴を取り込み
- 共有用リポジトリ shared の履歴情報を参照する、複製先リポジトリを作成
必要なことは、事前に以下の2つの設定を、$HOME/.hgrc
等のユーザ毎設定ファイルに記述するだけですから、これなら確認忘れやうっかりミスの心配は無さそうです。
- share エクステンションを有効化
- 共有用リポジトリ作成先を
[share] pool
で設定
なお、この挙動は全ての hg clone
実行において適用されますので、hg clone
の複製元が「ローカルホスト上のリポジトリ」であっても、複製先リポジトリは、共有用リポジトリと履歴を共有する構成になります。
共有リポジトリの識別方法
デフォルトの設定では、[share] pool
ディレクトリ直下に作成される共有用リポジトリには、履歴の最初(= リビジョン番号 0)のリビジョンのハッシュ値が使用されます。
「複製元 src に対応する共有用リポジトリ」の有無は、このハッシュ値を使って判定されますが、これは、hg push
や hg pull
等において、連携先が「由来が同じリポジトリ」か否かを判定する手法と同じものです。
このため、由来が同じ複数のリポジトリに対する hg clone
は、全て単一の共有用リポジトリに集約されます。
一般的には、この挙動で問題ないと思いますが、場合によっては「URL 違いの連携先は由来が同じでも別連携先」扱いしたいことがあるかもしれません。
そのような場合は、[share] poolnaming
設定項目に remote
を指定してください。この設定により、共有用リポジトリは、連携先 URL 毎に分離されるようになります。
なお、[share] poolnaming
に remote
を設定した場合でも、[share] pool
ディレクトリ直下に作成される共有用リポジトリの名前は、40桁のハッシュ値になります。
デフォルト設定の場合、このハッシュ値は「リビジョン 0 のハッシュ値」そのものですが、remote
設定の場合は、「連携先 URL 文字列をハッシュした値」なので、同じ40桁ハッシュ値であっても、意味が異なります。