Windows でも git difftool --dir-diff でシンボリックリンクを使う方法

git difftool --dir-diff が便利だよ、という話を git difftool --dir-diff が便利すぎて泣きそうです で書きましたが、1つ宿題が残っていました。Windows では一時ファイルがワーキング ディレクトリーへのシンボリックリンクにならないので、Unix や Mac に比べて、少しだけ不便だよ、という話です。

そこで、Windows でもシンボリックリンクを使えるようにしちゃおう、というのがこのエントリーの趣旨でございます。

Windows 向けの応急処置パッチ

Git for Windows 1.8.3 で動作確認しています。OS は Windows 7 (64 ビット)。

C:\Program Files (x86)\Git\libexec\git-core\git-difftool のパッチがこちら。

--- git-difftool    Sun Jun  2 11:28:06 2013
+++ git-difftool    Tue Jul  9 00:42:02 2013
@@ -283,7 +283,7 @@
            exit_cleanup($tmpdir, 1);
        }
        if ($symlinks) {
-           symlink("$workdir/$file", "$rdir/$file") or
+           !system("git", "mklink", "$workdir/$file", "$rdir/$file") or
            exit_cleanup($tmpdir, 1);
        } else {
            copy("$workdir/$file", "$rdir/$file") or
@@ -448,7 +448,7 @@
    my $indices_loaded = 0;

    for my $file (@worktree) {
-       next if $symlinks && -l "$b/$file";
+       next if $symlinks;
        next if ! -f "$b/$file";

        if (!$indices_loaded) {

適当な場所に保存して、GitBash を管理者権限で起動して適用してやります。

$ cd /c/Program\ Files\ \(x86\)/Git/libexec/git-core/
$ patch < ~/git-difftool.patch
patching file `git-difftool'

さらに、C:\Program Files (x86)\Git\libexec\git-core\git-mklink を作ります。

#!/bin/sh

cmd.exe /c "mklink \"$2\" \"$1\"" > /dev/null

(このスクリプトは /tmp/ といった msys 内のパスを Windows のパスに変換するために必要)

使い方

最初に、.gitconfig に difftool の設定をしておきます。WinMerge を利用するには次のようにしておきます。

[diff]
    tool = winmerge
[difftool winmerge]
    path = C:/Program Files (x86)/WinMerge/winmergeu.exe
    cmd = \"C:/Program Files (x86)/WinMerge/winmergeu.exe\" -r -u \"$LOCAL\" \"$REMOTE\"

GitBash を管理者権限で起動して、次のように実行します (Windows ではシンボリックリンクを作成するには管理者権限が必要)。

$ git difftool -d --symlinks [<commit> [<commit>]]

ついでに .gitconfig にエイリアスを定義しておくと便利でしょう。

[alias]
    d = difftool -d --symlinks

どうぞご利用ください。