Mercurial Queue の適用事例
コミット前レビュー
レビュアーによるレビューを済ませるまでは、共有リポジトリへの成果反映をさせたくない
『コミット前レビュー』によって、レビュアーから変更内容に対する何らかの指摘があった場合、指摘事項を反映させる必要があるため、何度も変更のやり直しを行う必要がある。
MQ を使用した作業手順
典型的な作業手順は以下の通り。
- 修正内容を MQ のパッチに記録する ("hg qnew" + "hg qrefresh")
- レビュアーに修正内容パッチを送付
- レビュアーはパッチをレビューし、採用の可否を判定
- 採用された場合:
- パッチを共有リポジトリに取り込む (誰が取り込むかは運用規則次第)
- 修正担当は、MQ 管理下のパッチを破棄 ("hg qdelete")
- 採用されない場合:
- レビュアーの指摘事項を元に、修正内容を改変 ("hg qrefresh")
- レビュアーに再度パッチを送付
- 以降、パッチが採用されるか、修正が取りやめになるまで上記手順の繰り返し
レビュアーへのパッチ送付には、以下の方法を用いることが可能。
- メールベースでの送付: "hg email -r 'mq()'" (要 patchbomb 拡張)
- Bug Tracker/Issue Tracker への upload:
- "hg export -r" 出力の貼り付け、ないしは
- .hg/patches 配下のパッチファイルの直接 upload
MQ を併用して変更のやり直しをする場合、以下のコマンドは出力が異なる:
- "hg diff": 作業領域の内容と、親リビジョン (= 直前の qrefesh 時点の内容) との差分
- "hg tip -p": 最後に適用されたパッチの内容
- "hg qdiff": 次に qrefresh した場合にパッチに取り込まれる内容(= "hg tip -p" + "hg diff")
例えば、前者は『レビュアーの指摘事項が適切に反映されている』ことの確認に、後者は『変更全体が妥当な内容である』ことの確認に使用できる。
作業順序と異なる順序で履歴に記録したい
作業手順上は「テストファースト」にしたいが、共有リポジトリに記録される履歴上は、『変更実施 ⇒ テスト作成』の順序にしたい。
履歴上の記録順序が『テスト作成 ⇒ 変更実施』となっている場合、"hg bisect" などで『テストがパスしなくなった原因リビジョン』の特定を行うと、『テスト作成 ⇒ 変更実施』の部分が該当してしまう。
そのようなリビジョン列の都度、"hg bisect" の探索が停止してしまうので、探索精度が著しく低下してしまう。
MQ を使用した作業手順
MQ を使用した典型的な作業手順は以下の通り。
- テストを書いて、障害が再現することを確認
- テスト追加分の修正を TEST に記録 ("hg qnew" + "hg qrefresh")
- 障害修正を実施して、障害が解決されていることを確認
- 障害修正を FIX に記録 ("hg qnew" + "hg qrefresh")
- 必要であれば、傷害修正は複数のパッチで記録
- FIX を外す ("hg qpop")
- TEST のテストにより、障害が再現することを再度確認
- FIX を再度適用 ("hg qpush")
- FIX の修正により、障害が解決されていることを再度確認
- TEST/FIX 内容が確定するまで上記手順を繰り返す
- 全てのパッチを一旦外す ("hg qpop -a")
- 先に FIX パッチ単体を適用 ("hg qpush --move")
- 次に TEST パッチを適用 ("hg qpush")
- 適用済みパッチを履歴に記録 ("hg qfinish")
パッチとして TEST/FIX を分割することで、障害が再現すること(= TEST の妥当性)や、修正による問題解決(= FIX の妥当性)の確認といった作業の間での行き来が、容易に行えるようになる。
固有修正を継続的に保守したい
ある成果物 A に修正 X を加えたいが、修正 X は成果物 A の開発元には取り込まれ無い。
また、成果物 A は随時更新されるため、適宜最新版に修正 X を適用したい。
例えば、OSS プロダクトに独自機能を追加するケースとして:
といったものが考えられる。
あるいは、環境依存/限定用途への対処を行うケースとして:
といったものが考えられる。
通常、このような修正は、対象成果物に取り込まれるのが一般的だが、以下の様な理由から、対象成果物の構成管理ラインには取り込まれないケースも考えられる。
- ライセンス問題/守秘義務が絡むために公開できない
- あまりに特殊なケースのため、開発元による取り込みが絶望的
- 契約内容に含まれていない成果であるため、発注元が受け取ってくれない
解決策の一つとして:
- 対象成果物のリポジトリを複製 ("hg clone" ないし convert/hgsubversion 等による別形式リポジトリからの取り込み)
- 独自変更用の名前付きブランチを作成
- 独自変更ブランチ上で独自変更を実施
- 適用対象リビジョンと独自変更ブランチを、独自変更ブランチ側でマージ
- 独自変更ブランチ側のマージ実施リビジョンから成果物をビルド〜利用
- 適用対象の開発が進んだ場合:
- 対象成果物リポジトリから取り込み
- 最新成果と独自ブランチを再度マージ
という運用が考えられるが、この方法では、独自変更を適用したリビジョンを得るためには、都度マージを実施しなければならない。例えば以下の様なニーズがある場合、これをマージで実現するのは現実的とは言えない。
MQ を使用した作業手順
MQ 管理領域の履歴管理
MQ 管理下にあるパッチを、複数のリポジトリで使用したい
MQ 管理下で作成したパッチの共有が必要な例としては:
- 作成されたパッチをチーム内で共有したい
- 作成されたパッチを複数の環境で適用したいが、パッチ内容の転送を scp/FTP 等で実施するのは面倒
あるいは、共有そのものは不要でも:
- 継続的に MQ パッチを更新するので、バックアップ代わりに変更履歴を記録しておきたい
MQ を使用した作業手順
- MQ 管理領域自体の構成管理を開始 ("hg init --mq")
- パッチを作成
- MQ 管理領域の状態は "hg status --mq" で参照可能
- パッチの追加 ("hg qnew") でパッチファイル状態が add に
- パッチの削除 ("hg qdelete") でパッチファイル状態は remove に
- パッチの更新 ("hg qrefresh") でパッチファイルの状態が modified に
- パッチ内容が確定した時点で MQ 管理領域の内容を履歴に記録 ("hg commit --mq")
- 連携先リポジトリでも MQ 管理領域の構成管理を開始
- 連携先リポジトリの MQ 管理領域に、管理領域の履歴情報を反映 ("hg push --mq")
- デフォルトの反映先は .hg/patches/.hg/hgrc での default-push/default 設定先
- .hg/patches/.hg/hgrc で列挙した連携先をコマンド行で指定可能
- 『連携先 URL』には、パッチ管理領域である『連携先リポジトリ + "/.hg/patches"』を指定する
- 連携先リポジトリで MQ 管理領域の内容を最新版で更新 ("hg update --mq")
- 連携先リポジトリでパッチ適用 ("hg qpush")
応用
管理対象となっている一連のパッチの中に、状況/環境によって、適用の要否が変化するパッチが存在する場合がある (例: 環境依存の解消/環境エミュレーションに相当するようなパッチ)。
このようなケースで、各パッチの適用の有無を実行時に制御するには、以下の機能を使用する。
- 各パッチ毎に "hg qguard" で「ガード」を設定 (設定は共有)
- "hg qselect" で「ガード」選択状況を設定 (各環境毎に設定)