Gitリポジトリの差分ファイルをGruntを使って抽出する
こんにちは、つみきのフロントエンドエンジニアの佐藤です。
クライアントワーク等では初回納品後に更新した内容を、差分だけで納品するケースは多いかと思います。
差分ファイルの抽出方法は様々かと思いますが、今回は Git で管理しているプロジェクトの更新分の差分ファイルを、 Grunt を使って抽出してみたいと思います。
git archive
Git にはファイルをアーカイブするコマンドが用意されています。
http://git-scm.com/docs/git-archive
git archive --format=zip HEAD -o archive.zip
例えば上記コマンドを叩くと HEAD
の内容でリポジトリ配下のファイルが zip アーカイブされます。
また以下のようにすれば指定ファイルやディレクトリのみの抽出も可能です。
git archive --format=zip HEAD filename.txt dirName -o archive.zip
filename.txt
と dirName
ディレクトリ以下のファイルが対象となります。
さらに以下のように git diff --name-only
でコミット間の差分ファイル名を返させれば、指定コミット間の差分抽出が可能です。
git archive --format=zip HEAD `git diff --name-only HEAD HEAD^` -o archive.zip
上記は HEAD
から 1 つ前のコミットとの差分を抽出してくれます。
Grunt
上記を利用し、Grunt タスクとして定義し、使用してみます。
Gruntfile
を用意します。
child_process.exec
Grunt でコマンドを実行するために Node.js のコアモジュールの child_process.exec
を利用します。
http://nodejs.org/api/child_process.html
Gruntfile
冒頭で exec
関数を用意します。
exec = require('child_process').exec
これで引数に実行したいコマンドを exec('ls')
のように渡して呼び出せば実行できます。
grunt.registerTask
次に実際に実行するタスクを書きます。
module.exports = (grunt) ->
grunt.registerTask 'diff', ->
exec 'git archive --format=zip HEAD `git diff --name-only HEAD HEAD^` -o archive.zip'
return
return
diff
という名前でタスクを登録しました。
これで下記のようにタスクを実行すれば、 1 つ前のコミットとの差分を抽出しアーカイブしてくれます。
grunt diff
オプション
実行するタスクに引数を渡せるようにして、汎用性を持たせてみます。
module.exports = (grunt) ->
grunt.registerTask 'diff', (format, dir, commitCount, fileName) ->
commandResult = ->
result = "git archive --format=" +
format +
" --prefix=" +
dir +
"/ HEAD `git diff --name-only HEAD HEAD~" +
commitCount +
"` -o " +
fileName;
result
command = commandResult()
exec command
return
return
タスク実行時に以下のように :
で区切って引数を渡して実行します。
grunt diff:zip:dirName:2:archiveName.zip
これで実際に実行されるコマンドは以下となり、
dirName
というディレクトリ名で、 HEAD
から 2 つ前のコミットとの差分ファイルを抽出し、 archiveName.zip
というファイル名でアーカイブが作成されます。
git archive --format=zip --prefix=dirName/ HEAD `git diff --name-only HEAD HEAD~2` -o archiveName.zip
プラグイン化
一連の処理を Grunt プラグイン化し npm レジストリへ公開しています。
https://www.npmjs.org/package/grunt-diff-archive
通常通りインストールします。
npm install grunt-diff-archive --save-dev
以下のようにタスクを定義し、実行できます。
grunt.initConfig(
diff:
target: {}
)
grunt.loadNpmTasks 'grunt-diff-archive'
grunt.registerTask 'default', ['diff']
現時点で指定できるオプションとデフォルト値は以下となっています。
grunt.initConfig(
diff:
options:
# ルートフォルダ名
pathName: 'root'
# アーカイブファイル名
fileName: 'archive'
# アーカイブフォーマット
format: 'zip'
# 基点となるコミットID
originCommit: 'HEAD'
# 対象のコミットID
targetCommit: 1
target: {}
)
タスクを実行します。
grunt diff
プラグインのライセンスは MIT です。
まとめ
差分ファイルの抽出は小規模の更新でしたらタイムスタンプでの目視確認等でも可能かと思いますが、ある程度規模が大きい更新となるとそれも難しくなってくるかと思います。
git archive
はその一つの方法として活用できるかと思います。