これはTortoiseHg Advent Calender 2012 18日目の記事です
※以下の内容は、Windowsのみを対象にしています。LinuxやMacの場合はいろいろ違うところがあると思います。
2012.12.27 修正
diffargsのプレースフォルダがまちがっていたので訂正しました
$plabel → $plabel1
イントロダクション
Merucurialで外部Diffツールを使いたいときは、ExtDiff Extensionを使って、こんな感じで設定する訳ですが、
[extdiff]
# 外部Diffツールのパスを指定
cmd.winmerge = C:\Program Files\WinMerge\WinMergeU.exe
# 渡すオプションを指定
opts.winmerge = /s /e
TortoiseHgもこの設定は見てくれるのですが、TortoiseHgの場合だと、Diffツールがインストールしてさえいれば、何の設定もしなくても使えるようになってますよね?
あれはどこに設定されているんでしょうか?
ぐぐってもなかなかそれらしい情報は見つからないんですが、TortoiseHgのインストールフォルダをGrepしてみると、どうやら hgrc.d\MergeTools.rc
というファイルに書かれているようです。
以下一部抜粋。
[merge-tools]
; Windows version of BeyondCompare 3
beyondcompare3.priority=-1
beyondcompare3.args=$local $other $base /mergeoutput=$output /ro /lefttitle=parent1 /centertitle=base /righttitle=parent2 /outputtitle=merged /automerge /reviewconflicts /solo
beyondcompare3.premerge=False
beyondcompare3.regkey=Software\Scooter Software\Beyond Compare 3
beyondcompare3.regkeyalt=Software\Wow6432Node\Scooter Software\Beyond Compare 3
beyondcompare3.regname=ExePath
beyondcompare3.gui=True
beyondcompare3.diffargs=/lro /lefttitle='$plabel1' /righttitle='$clabel' /solo /expandall $parent $child
beyondcompare3.diff3args=$parent1 $parent2 $child /lefttitle='$plabel1' /centertitle='$clabel' /righttitle='$plabel2' /solo /ro
beyondcompare3.dirdiff=True
ツール名.オプション = 値
という形式で指定していく訳ですね。
どんなオプションがあって、それぞれ指定するとどうなるのかをちょっと見てみました。
merge-toolsオプション
[2012.12.19 追記] この辺のオプションについては、 hg help config
にけっこうしっかり書いてましたw 気づいてなかった・・・
実行ファイルの検索につかう設定
regkey, regkeyalt, regname, regappend
ツールのフルパスを探し出すためのレジストリ情報を指定します。こんな感じのルールみたい。
-
HKEY_LOCAL_MACHINE{regkey} の、{ragname} の値をフルパスとして取得
{regname} が指定されていない場合は(規定)の値?
なければHKEY_CURRENT_USERも見る。 -
{regkey}に該当するキーがなければ、{regkeyalt}の方で試す
-
{regappend}が指定されている場合は、その値をフルパスに追加する
(レジストリにはフォルダパスが記述されていて、exeファイル名を付加しないとならない場合に使う)
executable
レジストリからフルパスを取れない場合はこっちで直接フルパスを指定します。
差分表示に関する設定
diffargs
差分表示の時に渡す引数です。
使えるプレースホルダは、以下の通り
プレースホルダ | 説明 |
---|---|
$parent または $parent1 | 比較元のパス |
$child | 比較先のパス |
$plabel1 | 比較元の表示名 |
$clabel | 比較先の表示名 |
diff3args
3way差分表示の時に渡す引数です。
3way差分表示に対応しているツールの場合は、マージリビジョンを選択して「親リビジョンとの差分」を表示したときに両方の親との差分が一度に見れる訳ですね。
※3way未対応の場合は1つ目の親リビジョンとの差分だけが表示されます。
使えるプレースホルダは、こうなります。
プレースホルダ | 説明 |
---|---|
$parent1 | 比較元1のパス |
$parent2 | 比較元2のパス |
$child | 比較先のパス |
$plabel1 | 比較元1の表示名 |
$plabel2 | 比較元2の表示名 |
$clabel | 比較先の表示名 |
dirdiff
True or Falseを指定します。
ディレクトリどうしの比較ができる場合はTrueを指定します。
リビジョン単位での差分をみる場合、ディレクトリ比較ができるツールの場合は直接ツールが起動されます。
できないツールの場合は、代わりにこんな画面が表示されます。
dir3diff
dirdiffの3way版のようです。
usewin
Trueを指定すると、dirdiff、dir3diffがTrueの場合でも上の「GUI差分表示」画面が表示されるようになります。
マージに関する設定
args
マージの時に渡す引数です。
プレースホルダ | 説明 |
---|---|
$base | 分岐元のファイルのパス |
$local | マージされるファイルのパス |
$other | マージするファイルのパス |
$output | 出力ファイルパス |
gui
GUIのあるツールの場合はTrueです。バッチで処理する時に間違ってGUIが起動されてしまわないようにするガード用です。
binary
バイナリファイルのマージができるツールの場合はTrueです。
fixeol
改行コードを勝手に変えちゃう可能性のあるツールの場合は、Trueを指定しておくとマージ後に直してくれるようです。
checkchanged
Trueを指定すると、処理後にファイルが変更されているかどうかのチェックを行います。
checkconflicts
Trueを指定すると、処理後にコンフリクトマーカーが消えているかどうかのチェックを行います。
premerge
Trueを指定すると、ツール起動前にinternal:merge相当の処理を実行して、失敗したときだけツールを起動するようになります。
Falseを指定した場合はいきなりツールを起動します。
と思いきや、 keep
という文字列を指定することもできるようになっているようです。
keep
を指定すると、Trueを指定した時と同じように先に internal:merge を実行するのですが、失敗した場合に、 出力ファイルにコンフリクトマーカを埋め込んだままで マージツールを起動します。
(Trueを指定した場合は、マージツール起動前に出力ファイルはinternal:merge前の状態に戻されます)
これを有効にした場合、 checkchangedではマージが成功したかどうか判断できなくなるので、適切な戻り値を返さないツールについてはcheckconflictsもあわせて指定する必要があります。
設定の調整
という訳で、もしプリセットされたツール設定が気に入らない場合は、このファイルから Mercurial.iniとかに設定をコピーしてきて、そこで修正すればOKです。
試しに、 僕が主に使っているWinMergeUの設定をいろいろ変えてみます。
起動オプションの変更
diffargに、 /e
というオプションが指定されています。
これは、 Esc
キーでプログラムを終了するという指定なのですが、ファイル単位の比較の時はともかくディレクトリ比較の時にはとても使いづらい(いくつもファイルを開くので、Esc
キーでは現在のファイルを閉じるだけにしてほしい)ので、このオプションを外します。
GUI差分表示画面の利用
ディレクトリ比較で直接ツールが起動されるのは確かに手軽なんですが、実は僕はあまり好きではありません。
というのは、そのモードだと、作業領域とあるリビジョンを比較したときに、ツール上で作業領域のファイルを修正することができなくなってしまうんですね。
(ディレクトリ比較モードだと、作業領域のファイルを直接開くのではなくてTempにコピーして開くため。もしかするとLinux版ではシンボリックリンクでよろしくやってくれるのかも)
差分ツール上で変更箇所を確認しながらコメントを書き足すとかよくやるのでこれはちょっと困る、ということで usewin = True
を指定します。
手抜きマージ
WinMergeも一応3wayマージの機能は持っているんですが、kdiff3などの本格的3wayマージツールの機能と比べてどうしても見劣りします。
この際、3wayマージはすっぱりとあきらめて(3wayマージが必要なときは他のツールを使うことにして)、WinMergeは簡易コンフリクト解消に特化する形の設定にすることにします。
WinMergeにはコンフリクトファイルを開く機能がある(コンフリクトマーカーを読み取って、localとotherを左右に振り分けて表示できる)ので、この機能を利用します。
オプション | 値 |
---|---|
premerge | keep |
args | /e $output |
checkconflicts | True |
まず、premerge = keep
とすることで、ファイルにコンフリクトマーカーを埋めたままWinMergeに渡せるようにします。
起動時の引数としては、単にコンフリクトファイルを渡すだけでいいので、 args = /e $output
となります。
さっき書いたとおり、 premerge = keep
の場合は checkchanged
は効かなくなるので、 checkconflicts
を使うようにします。
これで、手抜き版の設定ができました。3wayマージとくらべると情報量は減りますが、コンフリクトした個所だけをチェックできるので、効率的にマージを行うことができます。
まとめ
Mergeツール/外部Diffツールのプリセット定義は TortoiseHg\hgrc.d\MergeTools.rc
にありました。
プリセット定義をいろいろカスタマイズして、より快適なMercurialライフを送りましょう :)
ちなみにマージツールとしては今のところコストパフォーマンス含めて最強なのはkdiff3だと思います。日本語周りがちょっとアレですが・・・。
と思ったんですが、改めて使ってみるとBeyondCompare 3も悪くないかも。(前に試した時は何か残念なポイントがあったような気がするけど、それが何だったか思い出せませんw)