Mercurial Queues エクステンション
現在、このエクステンションは Mercurial とともに配布されています。
作者: Chris Mason
Contents
1. まえがき
通常、分散開発モデルでは changeset を変更できません。 一度 commit したものは、プロジェクトの履歴に永久に残ることになります。 これでは、プロジェクトメンテナに提出する一連の変更を作るのが面倒でしょう。 コードが成熟するにつれて、開発 repository には長い merges と変更の履歴が蓄積されます。 この履歴は開発者本人にとっては重要ですが、アップストリームに提出された時には非常にレビューしづらいものになるでしょう。
Andrew Morton はかつて、カーネルパッチを SCM の外部で管理するためのスクリプト一式を書きました。 そのスクリプトが拡張され、 quilt というスイートへ発展しました。 quilt の基本的な考えは、ソースファイルの代わりにパッチを管理するということです。 パッチは追加、削除、順序変更可能で、バグを直した場合や新しいバージョンへ追従した場合に更新(refresh)されます。 quilt はとても強力ですが、下層の SCM ツールと統合されていません。 そのため、変更内容を可視化するのは面倒です。
パッチキュー・エクステンションは quilt の機能を Mercurial と統合します。 変更内容は Mercurial にコミットされたパッチとして管理されます。 コミットは削除、順序変更可能で、 下位のパッチは working directory への変更をもとに更新(refresh)されます。 パッチディレクトリもバージョン管理下へ置くことができ、パッチへの変更を別個の履歴として管理することができます。
2. 設定
以下の行を設定ファイル(.hgrc or Mercurial.ini)へ追加し、エクステンションを有効にしてください:
[extensions] mq =
3. Mercurial Queues の利用
エクステンションを正しくインストールすると、 hg help に mq 系コマンドが追加されているはずです。 コマンド名は q で始まり、 quilt のコマンドをできるだけ真似ています。 パッチキューは .hg/patches というディレクトリにあります。 .hg/patches/series はパッチ適用順のリストです。 series ファイル内の順序を変えるだけで、パッチの順序を変更可能です。 series ファイルを編集する時は、適用中のパッチの項目を変更しないように注意してください。
4. パッチを新しいアップストリーム・バージョンとマージ
Rebase エクステンション を使うと、一連のパッチをアップストリームの最新ヘッドとマージするのがかなり楽になります。たいていの場合、やることはたったのこれだけです:
$ hg pull $ hg rebase -s <rev1> -d <rev2>
このコマンドは、 rev1 (要は mq に紐付いた最も古い適用済みリビジョン)とその子孫を、 rev2 (pull したばかりの最新ヘッド)へリベースします。必要に応じてマージが行われます。リベースしたいパッチは適用済みでなければなりません。 qpop したパッチは対象になりませんから。リベース後も、一連のリビジョンは依然として mq に紐付いており、 mq で管理された先のリビジョンへ戻って編集することができます。
5. チュートリアル
mq について詳しくは MqTutorial をご覧ください。
6. フックの例
たいていの場合は、パッチを適用したリポジトリから変更内容を push または pull したくないでしょう。 うっかりやってしまわないように、 hook をリポジトリの .hg/hgrc へ追加しましょう。
Mercurial 0.9.2 以降では、 --force オプションなしで push することはありません。 -- ThomasArendsenHein 2007-01-05 08:36:33
[hooks] # MQ パッチ適用中 は "hg pull" を防止 prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1 # MQ パッチ適用中 は "hg push" を防止 preoutgoing.mq-no-push = ! hg qtop > /dev/null 2>&1
Mercurial 2.1 以降では、 mq secret フェーズサポート を使ってみるとよいでしょう。
7. コマンドの例
cd some_existing_hg_repository # パッチキュー・ディレクトリをセットアップ (Mercurial 1.5 で非推奨に) hg qinit # firstpatch という名前のパッチを作る hg qnew firstpatch # ファイルを変更 vi filename # 変更内容でパッチを更新 hg qrefresh # vi .hg/patches/firstpatch で結果を見て # 現在のパッチの内容を画面に出力 hg qdiff # さらに変更 vi filename # パッチに保存されていない差異を見る hg diff # パッチを更新 hg qrefresh # 別のパッチを作る hg qnew secondpatch # さらなる変更を加え、パッチを更新 vi filename hg qrefresh # 適用中のパッチを調べる # キューにある全パッチを見る hg qapplied hg qseries # 最上位のパッチを取り除く hg qpop # そのパッチを再度適用 hg qpush # パッチを全て取り除く hg qpop -a # パッチを全て適用 hg qpush -a
8. 小ワザ
8.1. 適用中のパッチを全て E-Mail
hg email qbase:qtip
8.2. 適用中のパッチを恒久なチェンジセットへ変換
hg qfinish -a
8.3. 適用中のパッチを1つのパッチにまとめて出力
hg diff -r qparent:qtip
8.4. 一時的に作業をよけて後で再開
git stash に当たる操作は、 Mercurial ではこうなります。
hg qnew choosename hg qpop # ... # restore hg qpush hg strip -k choosename hg qremove choosename
8.5. パッチを常に git 拡張フォーマットに
以下を .hgrc へ追加
[diff] git=1
8.6. qrefresh でタイムスタンプを更新しない
パッチキューをバージョン管理下に置いている場合は、 qrefresh する度にパッチのタイムスタンプが更新されてイライラするかもしれません。 タイムスタンプを更新させたくない場合は、以下を .hgrc へ追加してください。
[diff] nodates=1
8.7. qstatus コマンドの追加方法
以下を .hgrc へ追加 (詳しくは AliasExtension を):
[alias] qstatus = status --rev -2:.
他には "status --rev qparent:." や "status --rev qparent:qtip" というエイリアスが有用でしょう。
8.8. パッチのコミットメッセージを更新
1 行メッセージを書き換えるだけなら、こうしてください:
hg qrefresh -m "新しいメッセージ"
メッセージが複数行に及ぶ場合はこうです:
hg qrefresh -e
$EDITOR が開くのでコミットメッセージを編集してください。
8.9. パッチの公開
パッチキューで長い間操作していると、公開リポジトリを継続的に最新の変更内容で更新するのに辟易することと思います。 フックを使えば一連の処理をかなり自動化できます。 ここにリポジトリが2つあるとします。ひとつは基本のリポジトリで、もうひとつは hg qinit -c で作成するようなパッチのリポジトリです。
パッチリポジトリ(メインリポジトリのルートの中、 .hg/patches)に、次の changegroup フックをセットアップしましょう:
[hooks] # 最新バージョンのパッチをチェックアウト changegroup.1update = hg update # ベースリポジトリから古いバージョンを pop changegroup.2pop = hg -R ../.. qpop -a # 今チェックアウトしたところのバージョンを push changegroup.3push = hg -R ../.. qpush -a
もし手の込んだ事が好きなら, パッチ・リポジトリを別のフックで公開することもできます:
changegroup.publish = hg push ../../../patches/foo
この方法で overlay patch queue を http://hg.kublai.com/mercurial/overlay へ公開しています。
8.10. パッチキューの変更を常に secret フェーズにする
互換性の問題で 、 mq パッチはデフォルトで secret phase になりません。つまり、パッチを他のリポジトリとやり取りできてしまいます。たいていこれは好ましくありませんから、設定で secret フェーズサポートを有効にできるようになっています:
[mq] secret = True
9. Strip
strip コマンドはパッチキューをはっきりとは使いませんが、 mq エクステンションの一部です。
10. 関連項目
EditingHistory に Mercurial Queue の上手な使い方があります。
qrecord コマンドについては RecordExtension を参照ください。
11. 外部リンク
第12章 「 Mercurial Queue で変更を管理する」 http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html