共通でないチェンジセットを見分ける

posted by Steve Losh on December 9, 2009

この Tip は mercurial-devel メーリングリストメール からヒントを得ています。

簡単に言うとこの質問は、 リビジョン X に含まれていて、 リビジョン Y含まれていない チェンジセットはどうすれば分かるのか? ということです。これは例えば、 あなたが使用しているソフトウェアのアップデートに際して、 旧版から新版までの変更点を全て把握したい時に便利です。

ことは簡単そうに見えますが、 気をつけなければならない微妙な問題がいくつかあります。

注: この Tip では、コマンドの結果を読みやすくするため、標準の hg log の代わりに shortlog エイリアス を利用します。 hg log でも全て同じように動作しますので、 詳細な出力のほうがよければ、いつでもそちらを使ってください。 (hg sloghg log にテンプレート指定を追加しただけのエイリアスです。)

簡単な (間違った) 方法

まずは、リビジョンを一覧する一番簡単な方法から始めましょう。 --rev オプションです。 このようなグラフの単純なリポジトリがあるとします:

$ hg glog
o  4 Fix another bug. (6 seconds ago by Steve Losh) tip 
|
o  3 Fix a bug. (16 seconds ago by Steve Losh)  
|
@  2 Add another simple feature. (34 seconds ago by Steve Losh)  
|
o  1 Add a simple feature. (40 seconds ago by Steve Losh)  
|
o  0 Initial revision. (7 minutes ago by Steve Losh)

現在のリビジョンが 2 で、 tip へアップデートすると何が変わるのか知りたい場合は、 こんな風にするのではないでしょうか:

 $ hg slog --rev 2:tip
 2 Add another simple feature. (5 minutes ago by Steve Losh) 
 3 Fix a bug. (5 minutes ago by Steve Losh) 
 4 Fix another bug. (5 minutes ago by Steve Losh) tip

結果にリビジョン 2 が入っていることが分かると思います。 これは現在のリビジョンなのでリストに含まれるべきでありませんが、 恐らく大した問題でありません。ただ無視すればよいだけですから。

しかし、リポジトリに同時進行中のブランチが複数ある場合、 この手の方法は上手くいきません。例えば:

$ hg glog
@  6 Fix a critical bug. (1 second ago by Steve Losh) tip 
|
| o  5 Start the rewrite of the UI. (24 seconds ago by Steve Losh)  ui-rewrite
| |
o |  4 Fix another bug. (8 minutes ago by Steve Losh)  
| |
o |  3 Fix a bug. (8 minutes ago by Steve Losh)  
| |
o |  2 Add another simple feature. (9 minutes ago by Steve Losh)  
|/
o  1 Add a simple feature. (9 minutes ago by Steve Losh)  
|
o  0 Initial revision. (16 minutes ago by Steve Losh)

$ hg slog --rev 2:tip
2 Add another simple feature. (9 minutes ago by Steve Losh) 
3 Fix a bug. (9 minutes ago by Steve Losh) 
4 Fix another bug. (9 minutes ago by Steve Losh) 
5 Start the rewrite of the UI. (54 seconds ago by Steve Losh) 
6 Fix a critical bug. (31 seconds ago by Steve Losh) tip

hg slog コマンドの結果にチェンジセット 5 が含まれてしまっています。 このリビジョンは他のブランチですから、実際に 2 から tip (6) へアップデートした場合、 5 の変更点は含まれません。

リビジョンを範囲指定した場合、 Mercurial は番号順にリビジョンを辿るため、 このようになります。つまり 1:4 は、実際には「どのブランチの変更点かによらず 1234 」という意味になります。

hg log に他のオプションを指定すると、この課題に上手く対処することができます。

正しい方法

取り組んでいる問題について少し距離を置いて考えると、 この問題を単純な定義へまとめ直せることが分かります。目的のチェンジセットの条件は:

1 つ目の条件は、 --rev--follow オプションの組み合わせでこのように表現できます:

$ hg slog --rev tip:0 --follow
6 Fix a critical bug. (11 minutes ago by Steve Losh) tip
4 Fix another bug. (20 minutes ago by Steve Losh) 
3 Fix a bug. (20 minutes ago by Steve Losh) 
2 Add another simple feature. (20 minutes ago by Steve Losh) 
1 Add a simple feature. (21 minutes ago by Steve Losh) 
0 Initial revision. (28 minutes ago by Steve Losh)

別ブランチの余計なチェンジセットは表示されていません。

--rev DESTINATION:0--follow 付きで指定すると、 「 DESTINATION の祖先のチェンジセットを全て表示する」という意味になります。 各オプションの詳細は hg help log をチェックしてください。

あともう 1 つだけやることがあります — 現在のリビジョンで既に含まれているチェンジセットを、 リストから除外することです:

$ hg slog --rev tip:0 --follow --prune 2
6 Fix a critical bug. (16 minutes ago by Steve Losh) tip
4 Fix another bug. (25 minutes ago by Steve Losh) 
3 Fix a bug. (25 minutes ago by Steve Losh)

よし! チェンジセット 6, 4, 3 は、サンプルリポジトリで 2 から 6 へアップデートした場合に有効になるチェンジセットです。

コマンドを一般化すると、このようになるでしょう:

hg slog --rev DESTINATION:0 --follow --prune SOURCE

もちろん、リビジョン指定の標準的なショートカットは全て利用できます。 現在作業中のリビジョンから tip へアップデートする時に含まれるものを調べるには:

hg slog -r tip:0 -fP .

注: このコマンドは、「過去へ」アップデートする時には 上手くいきません 。 このコマンドが表示するのは、これから追加されるチェンジセットのみです — SOURCE に含まれて DESTINATION含まれない チェンジセットについては関知しません。

リビジョン X に含まれていて Y無い チェンジセットは、 どうやって見分けるの?