案件で「作業の差分を納品してくれ」とか言われることってよくあります。
今までは手作業でディレクトリ作って、ファイルをコピーしてましたが、
もう、そんなうんざりする作業とはおさらばできそうです。
git archive
と git diff
の合わせ技で差分を出力できる事がわかったからです。
例えば、一個前のコミットから現在のコミットまでの差分を取り出したい時は、
git archive --format=zip --prefix=root/ HEAD `git diff --diff-filter=d --name-only HEAD^ HEAD` -o archive.zip
まずは、git archive
について。
--format=zip
を付けるとzipで固めてくれます。
--prefix=root/
は抽出したファイルをrootディレクトリに入れた状態にしてくれます。
-o archive.zip
で出力先と出力名を指定しています。
HEAD
は抽出元のコミットで、
抽出したいファイルやディレクトリをgit diff
を使って指定しています。
git diff
は --name-only
を付けると、ファイルのパスを返してくれるのです。
--diff-filter=d
オプションで不要な削除の差分をフィルタリングすると、
差分ファイルに必要なファイルパス一覧が取得できます。
例では、HEAD^
と HEAD
のコミット間での差分のファイル一覧が返るので、
それを git archive
がzipにしてくれるというわけです。
関数化した
毎回コマンド書くのは辛いので、
関数化してみました。
zshとbashで動作を確認しました。
function git_diff_archive()
{
local diff=""
local h="HEAD"
if [ $# -eq 1 ]; then
if expr "$1" : '[0-9]*$' > /dev/null ; then
diff="HEAD~${1} HEAD"
else
diff="${1} HEAD"
fi
elif [ $# -eq 2 ]; then
diff="${2} ${1}"
h=$1
fi
if [ "$diff" != "" ]; then
diff="git diff --diff-filter=d --name-only ${diff}"
fi
git archive --format=zip --prefix=root/ $h `eval $diff` -o archive.zip
}
引数なしで git_diff_archive
と呼ぶと HEAD
を丸っとzipにします。
git_diff_archive
引数に数値を指定すると、HEAD
と HEAD~数値
の差分を抽出します。
つまり、数値分前のコミットからの差分になります。
git_diff_archive 数値
引数にコミット識別子(IDとかHEADとかHEAD^とかdiffの引数として使えるもの)を指定すると、
HEAD
と コミット識別子 の差分を抽出します。
IDで一発指定したい時とか便利です。
この時、HEADよりも新しいIDとかは渡さないようにしてください。
想定している抽出物を得られない可能性が高いです。
git_diff_archive コミット識別子
コミット識別子を2つ渡すと、その2つのコミットの差分を抽出します。
ちょっと前のバージョンの差分が欲しいとか言われたときに使えます。
渡す順番は新しいコミット、古いコミットの順番で渡してください。
間違うと、想定している抽出物を得られない可能性が高いです。
git_diff_archive コミット識別子1 コミット識別子2
何かおかしなところがありましたら、
やさしいツッコミお待ちしております。
修正履歴
2015/06/25
引数を1つだけ渡すときに、数字で始まるコミットIDを渡すとエラーが起きていました。
2015/06/24
差分にファイルの削除が含まれると、それも差分として一覧に追加されてしまい、
zipに固めるときにファイルがなくてエラーになってました。
2016/11/05
git diff
に渡すコミット識別子の順番を入れ替えました。
以前の順番だと、新しいコミットから古いコミットを比べた差分になってしまい、
差分が上手く取得できないケースがありました。
それにともない --diff-filter
も D
から d
に変更しました。