k-holyのPHPとか諸々メモ

Webで働くk-holyがPHP(スクリプト言語)とか諸々のことをメモしていきます。ソースコードはだいたいWindowsで動かしてます。

Windowsでgitコミット差分抽出+ZIPアーカイブを生成するバッチファイル

git diff コマンドと git archive コマンドを利用した差分抽出については知ってはいたんですが、しばらくFTPでのアップロードが必要なプロジェクトから逃れていたこともあり、あまり追求していませんでした。

今回再びそのような環境に携わることになりましたので、Windowsで実現する方法を調べて試してみたところ、以下のようなバッチファイルでうまくいきました。

git-archive-diff.bat

@echo off
setlocal ENABLEDELAYEDEXPANSION
set DIFF_LIST=
set NEW_SHA=%1
set OLD_SHA=%2
if "%OLD_SHA%" == "" (
  set OLD_SHA=%NEW_SHA%
  set ARCHIVE="%NEW_SHA:~0,7%.zip"
) else (
  set ARCHIVE="%OLD_SHA:~0,7%-%NEW_SHA:~0,7%.zip"
)
for /f "usebackq" %%A in (`git diff --name-only --diff-filter=AM %OLD_SHA%..%NEW_SHA%`) do set DIFF_LIST=!DIFF_LIST! %%A
git archive --format=zip HEAD -o %ARCHIVE% %DIFF_LIST%
endlocal

SourceTreeから実行

自分はこのバッチファイルをSourceTreeから利用していますので、参考までに設定の手順を記しておきます。

適当な場所に配置した上で、 [Tools] → [Options] → [Custom Actions] → [Add] でカスタムアクション名とバッチファイルのパスを指定し、パラメータに $SHA と入力します。

例ではカスタムアクション名を「archive-diff」としています。オプションのチェックボックスはチェックしなくていいです。

差分を抽出したいコミットを2つ選択し、右クリックから [Custom Actions] → [archive-diff] と選択すると、登録したバッチファイルが実行され、リポジトリのルートに差分を抽出したZIPファイルが作成されます。

コマンドラインから実行

$ git-archive-diff {新しい方のコミットID} {古い方のコミットID}

引数で指定するコミットIDの順序が直感的ではありませんが、SourceTreeのカスタムアクションの仕様に合わせてこうなっています。

コマンドラインで利用する場合はバッチファイルの set NEW_SHA=%1set OLD_SHA=%2 のところを %1 ←→ %2 として、引数を入れ替えた方が分かりやすいかもしれません。

参考

スクリプトの内容は、こちらの質問および回答を参考にさせていただきました。(参考というかほとんどそのままです…)

git diffコマンドにdiff-filterオプションを追加したのと、出力ファイル名をコミットIDから生成する処理を追加しただけです。

回答にもありますが、コマンドプロンプトや変数で扱える文字数に制限がある(8191文字?)とのことで、対象ファイルが多い、またファイル名が長いとエラーが発生するかもしれません。

なお、以下のMicrosoft技術情報はWindows XPのものですが、長すぎるパラメータはファイルから読み込むようにすればこの制限を回避することができるようです。

以下の記事はバッチファイルの仕様を把握するのにお世話になりました。

PHPは言語仕様がクソ」とかよく言われますが、PHPの文法は分かりやすいよなぁ、というのが真性PHPerな自分の正直な感想です…。

(記号ばっかり…同じ記号の意味が文脈で変わる…エスケープどうすればいいの…なんでコマンドラインとバッチファイルで違うの…みたいな)