TECH BOX

Technology blog from Web Engineer

この記事は最終更新日から4年以上経過しているため正確ではないかもしれません

fish shellでコミット差分アーカイブのコマンドファイルを作成する

gitには特定のコミットから最新までの差分や、特定のコミット間の差分をzipにするコマンドがあります。

$ git archive --format=zip HEAD `git diff --name-only --diff-filter=d 古いコミットハッシュ 新しいコミットハッシュ` -o archive.zip

こんな感じのやつです。

このコマンドをシェルスクリプトにして配布しているサイトはいくつもあるけどfish shellでの書き方を紹介しているサイトが見つからなかったので紹介します。

注意
シンプルなスクリプトにしているのでHEAD~3のようにHEADからコミットを遡るパターンには対応していません

完成形

まずは完成形のロジックを紹介します。

# gitzip.fish
function gitzip
  set -l d (date '+%y%m%d_%H%M')
  set -l p (basename $PWD)
  set -l diff ""
  set -l length (count $argv)

  if test $length -ge 2
    set diff $argv[1] $argv[2]
  else if test $length -eq 1
    set diff $argv[1] HEAD
  end

  command git archive --format=zip HEAD (git diff --name-only --diff-filter=d $diff) -o ~/Downloads/$p-$d.zip
end

これで$ gitzip コミットハッシュでコミットハッシュから最新まで。
$ gitzip 古いコミットハッシュ 新しいコミットハッシュでコミットハッシュ間の差分をDownloadディレクトリにzipで作成します。
※新しいコミットハッシュ、古いコミットハッシュの順でも動作はします

それでは一つずつ解説していきます。

zipファイル名をプロジェクト名-日付.zipにする

archive.zipのように決め打ちでもいいですがそれだと上書きされたりするし、放置したときになんのアーカイブか分からなくなる事もあるのでユニークにします。

# 日付
set -l d (date '+%y%m%d_%H%M')

# 現在いるディレクトリ名
set -l p (basename $PWD)

アーカイブを作成するときにはたいていプロジェクトディレクトリからコマンドを打つはずなのでそのディレクトリ名をファイル名にします。

引数の数で特定コミット間か最新コミットまでかを判断する

引数が一つの場合はコミットからHEADまでを取得し、2つのときはそのコミット間をセットするようにします。
ちなみに3つ以上のときは前2つのみしか使いません。

set -l diff ""
set -l length (count $argv)

if test $length -ge 2
  # 引数が2つ以上の時
  set diff $argv[1] $argv[2]
else if test $length -eq 1
  # 引数が1つの時
  set diff $argv[1] HEAD
end

fishの場合、引数は$argvで取得できる決まりになっています。

引数の数はcount(xxx)で取得できますが、count(xxx)と書くとログに出力されるためif文が動作しません。
そこでset -l length (count $argv)と一度変数に入れて置きます。

if test [条件式]でファイルや文字列数値のテスト行います。
if test $length -ge 2だとJSでいうif ($length >= 2)に該当します。
-eq=になります。

条件式に関してはfishのtestを参照。

gitコマンドを実行する

command git archive --format=zip HEAD (git diff --name-only --diff-filter=d $diff) -o ~/Downloads/$p-$d.zip

アーカイブを生成するためのgitコマンドを書きます。コマンドはcommandで実行できます。
~/Downloads/はMacのDownloadsディレクトリを指します。
Windowsや他の場所にしたい場合は適宜変更するのもよしです。

diff-filter=dは削除ファイル以外というフィルタになります

fishで使えるようにする

ここまで作成したロジックをgitzip.fish(fishはfishファイルの拡張子)で保存します。
保存する場所はどこでもいいです。

このファイルを起動時に読み込むようにするためcongig.fishに下記を追加します。
config.fishはMacだと~/.config/fish/config.fishにあります(Windowsはちょっとわかりませんが…)

set -x PATH $PATH 保存場所のパス/gitzip.fish

これでgitzipコマンドが利用できます。

利用方法

$ gitzip コミットハッシュ
# or
$ gitzip コミットハッシュ1 コミットハッシュ2

第1引数のコミット位置を基準に第2引数までのコミット(省略した場合はHEAD)までの差分ファイルを取得


fishでもシェルスクリプトファイルと同じようにgit archiveを自動化したい人は参考にしてください。