Githubのdiffとarchiveで差分ファイル一覧を抽出する
はじめに
「作業したファイルをリスト化してほしい」なんてことを言われる日が来るとは思いませんでした。
一体そんなものを出してどうするんだ、そもそもその作業はこちらがやらなければいけないのか、手作業では絶対にやりたくない。。。
そんな思いに駆られながらググっているとGit管理できていればなんとかなるみたいですね。
それに、作業したファイルをリスト化したいって意外とあるあるみたいですね。備忘録として記事にしました。
Githubのコマンド一発で差分を抽出しましょう。
とりあえず差分を抽出する
あるブランチのコミットID:AからコミットID:Bまでの差分を抽出したい場合は以下のコマンドで抽出できます。
git archive {ブランチ名} `git diff --name-only {コミットID:A} {コミットID:B}` -o {出力ファイル名}
なので例えば、developブランチの最新から1つ前の差分をarchive.zipに出力する場合は以下のコマンドです。
git archive develop `git diff --name-only HEAD HEAD~1` -o archive.zip
何をやってるの?
大きく分けると、git diff
と git archive
で役割を分けています。
git diff
特定のコミットの間で発生した差分を抽出しています。
また、git diff
では --name-only
のオプションを使用してファイル名だけを取得しています。
git archive
git archive
で抽出された差分をアーカイブ(zipファイル化)しています。
エラーが出る場合の対処
git archive
できないファイルがある場合は以下のようなエラーが出ます。
fatal: pathspec '{ファイル名}' did not match any files
この場合はエラーの原因ファイルをsedコマンドで除外することで対応します。
git archive {ブランチ名} `git diff --name-only {コミットID:A} {コミットID:B}| sed '{除外するファイル}'` -o {出力ファイル名}
例えば .DS_Store ファイルが原因でエラーが出ている場合は以下のようになります。
git archive develop `git diff --name-only HEAD HEAD~2| sed '.DS_Store'` -o archive.zip
コマンドの併用でだいぶ長くなりましたが、これで目的はほぼ達成できました。
抽出されたファイルのパスをリスト化
抽出されたzipファイルの中身のパスをリスト化します。
zipinfoコマンドを使用してzipファイル内のファイル名を1行ずつ出力して保存します。
zipinfo -1 {抽出したzipファイル} > {出力先ファイル}
例えば、今回のarchive.zipのファイル名をresult.txtに出力する場合は以下のようになります。
zipinfo -1 archive.zip > result.txt
zipinfoのオプションで -1 を指定していますが、ここのオプションを変更することで圧縮率やタイムスタンプなど詳細場情報を出色することもできます。
-xを指定すれば特定のファイル名を出力から除外することもできます。
最適化
これでコミットAからコミットBまでの差分のファイルをリスト化できました。
ただ .gitignore など不要なファイルもリスト化されているので、必要に応じて不要ファイルを除外する必要があります。
.gitignoreは.gitattributesに .gitignore export-ignore
を記述することでarchiveの対象外にできるみたいです。
他にも必要に応じて不要なファイルを除外する必要はありそうですが、多くなければ人力でやっても良いのかなと思います。
おわりに
「作業したファイルをリスト化してほしい」なんてことを言われた日にはこの記事を思い出してください。
次はお前の番です。
そもそも
差分ファイル一覧だけなら git archive
のくだりは必要なくて、以下のコマンドでよかった。
git diff --name-only {コミットID:A} {コミットID:B} > {出力先ファイル}
参考記事
Discussion