Mercurial Queues エクステンション

現在、このエクステンションは Mercurial とともに配布されています。

作者: Chris Mason

1. まえがき

通常、分散開発モデルでは changeset を変更できません。 一度 commit したものは、プロジェクトの履歴に永久に残ることになります。 これでは、プロジェクトメンテナに提出する一連の変更を作るのが面倒でしょう。 コードが成熟するにつれて、開発 repository には長い merges と変更の履歴が蓄積されます。 この履歴は開発者本人にとっては重要ですが、アップストリームに提出された時には非常にレビューしづらいものになるでしょう。

Andrew Morton はかつて、カーネル patchSCM の外部で管理するためのスクリプト一式を書きました。 そのスクリプトが拡張され、 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. パッチを新しいアップストリーム・バージョンとマージ

MqMerge で詳しく説明します。

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

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 拡張フォーマットに

以下を .hgrc へ追加

[diff]
git=1

8.5. qrefresh でタイムスタンプを更新しない

パッチキューをバージョン管理下に置いている場合は、 qrefresh する度にパッチのタイムスタンプが更新されてイライラするかもしれません。 タイムスタンプを更新させたくない場合は、以下を .hgrc へ追加してください。

[diff]
nodates=1

8.6. qstatus コマンドの追加方法

以下を .hgrc へ追加 (詳しくは AliasExtension を):

[alias]
qstatus = status --rev -2:.

他には "status --rev qparent:." や "status --rev qparent:qtip" というエイリアスが有用でしょう。

8.7. パッチのコミットメッセージを更新

1 行メッセージを書き換えるだけなら、こうしてください:

hg qrefresh -m "新しいメッセージ"

メッセージが複数行に及ぶ場合はこうです:

hg qrefresh -e

$EDITOR が開くのでコミットメッセージを編集してください。

8.8. パッチの公開

パッチキューで長い間操作していると、公開リポジトリを継続的に最新の変更内容で更新するのに辟易することと思います。 フックを使えば一連の処理をかなり自動化できます。 ここにリポジトリが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 queuehttp://hg.kublai.com/mercurial/overlay へ公開しています。

9. Strip

strip コマンドはパッチキューをはっきりとは使いませんが、 mq エクステンションの一部です。

10. 関連項目

11. 外部リンク


CategoryJapanese

English