Mercurialのマージ作業にはまる

Mac環境でMercurialを使って作業。変更点をコミット(hg commit)した後、サーバのリポジトリへ更新をかける(hg push /path/to/server)が失敗してしまう。サーバの更新をローカルへ反映(hg pull /path/to/server)させてみたら、headが2つになった(hg heads)のでマージ(hg merge)を行う。(ここまでは良くある作業)

しかし、自分一人しか使っていないリポジトリなのに、なぜかコンフリクトが発生したというエラーメッセージが表示される。どうやら最新のリビジョンではなく、古いリビジョンを使って作業していたらしい。コンフリクトしたファイルを手作業で編集して再度コミット(hg commit)するが、失敗してしまう。考えてみればマージ作業を行うためのエディタが起動してこないのが変だ。要するにマージ作業自体がMercurialに伝わっていないらしい。この状態で更新(hg update)やマージ(hg merge)コマンドを試しても全て失敗してしまう。

$hg update
abort: outstanding uncommitted merges
$hg merge
abort: outstanding uncommitted merges

そんなわけで、Mac環境でマージ作業を行うための設定を行う。下記のサイトにはopendiff-wを使えと記載されているが、実際にはFileMerge.appは起動しなかった。

To use FileMerge with extdiff on Mac OS X, create the following shell script called opendiff-w somewhere in your $PATH

[merge-tools]
filemerge.executable = opendiff-w
MacOSXFileMerge - Mercurial/FileMerge on Mac OS X

正しくは、下記の情報に従ってfmdiffを用意して指定する必要がある。この方法で、FileMerge.appが起動してマージ作業が出来ることを確認した。

The provided command-line wrapper "opendiff" for "FileMerge.app" will not work with ExtdiffExtension. Instead, use the script fmdiff which wraps "FileMerge.app" so that it responds like the usual diff program.

[extdiff]
cmd.opendiff =  fmdiff
TipsAndTricks - Mercurial/13. Using FileMerge.app/opendiff as the diff program (OS X)

手順をまとめるとこのようになる。

1. ~/opendiff-wに下記を追記。

#!/bin/sh
opendiff "$@" | cat

2. ~/.hgrcに下記を追記。

[merge-tools]
filemerge.executable = /Users/foo/opendiff-w
filemerge.args = $local $other -ancestor $base -merge $output
[extensions]
hgext.extdiff =
[extdiff]
cmd.opendiff = fmdiff

3. 下記リンク先のスクリプトを/usr/local/bin/fmdiffに入れる。

Apple's Developer Tools for Mac OS X include FileMerge, a graphical tool to compare and merge files. FileMerge can be much handier to use, unfortunately, it doesn't integrate with Subversion straightforwardly. It can be opened from the command line with the opendiff command, but its interface differs from that of diff and diff3. It returns immediately (i.e. it forks and does not block) and it expects different arguments. Some wrapper scripts are thus required to call FileMerge from Subversion.

[http://ssel.vub.ac.be/ssel/internal:fmdiff:title=Using FileMerge as a diff command for Subversion [SSEL]]

準備作業が整ったので、コンフリクト箇所のマージ作業を再度行う。

1. ワーキングコピーの変更箇所を強制クリアする。

$hg update -C

2. マージを行う。今度はFileMerge.appが起動するので、編集を行いファイルを保存する。

$hg merge

3. マージ結果として、下記のステータスが表示されればOK。

1 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

4. 変更箇所をコミットする。

$hg commit -m "hoge"

慣れてしまえば簡単なことなのだけど、Mercurialの流儀に慣れるまではなかなか大変だ。