Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
541
Help us understand the problem. What is going on with this article?
@kaminaly

gitで差分ファイルを抽出する

More than 3 years have passed since last update.

案件で「作業の差分を納品してくれ」とか言われることってよくあります。
今までは手作業でディレクトリ作って、ファイルをコピーしてましたが、
もう、そんなうんざりする作業とはおさらばできそうです。
git archivegit 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

引数に数値を指定すると、HEADHEAD~数値 の差分を抽出します。
つまり、数値分前のコミットからの差分になります。

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-filterD から d に変更しました。

541
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kaminaly
SHIFTBRAIN Inc. 所属。 広く深い海の真ん中で溺れるようにプログラム書いています。 エナジーはレッドブル派。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
541
Help us understand the problem. What is going on with this article?