git archive で gitattributes の export-ignore を無視して全データを取得するメモ

git archive で gitattributes の export-ignore を無視して全データを取得するメモ

git archiveで gitattributes の export-ignore を無視して全データを取得するメモです。

背景

最近、gitattributes の export-ignore が便利で使ってます。GitHub でのソース一式の ZIP ダウンロード時にファイルを除外できるので、先方への納品ファイルを作るときに重宝してます。

しかしながら、悩ましいところもありまして。ファイルを除外してしまうので完全に全ファイルほしいときにも、当たり前なんですけど除外されちゃうんですよ。

つまり、リポジトリの中身を丸ごとアーカイブしたくて git archive を使ったら、一部のファイルがごっそり抜け落ちていてびっくり。

試した方法

最初は git archive で押し通そうと --worktree-attributes を使えばいけるかと思ったんですが、これは「worktree上の .gitattributes を見る」というオプションで、単体では無効化にはなりません。

しかも git archive はデフォルトだと worktree ではなくアーカイブ対象コミット内の .gitattributes を見に行くので、うっかりworktree上のファイルだけ消しても効果がなくて地味にハマりました。

# これだけでは export-ignore は無視されない
git archive --worktree-attributes --format=tar.gz -o archive.tar.gz HEAD

ちゃんとやるなら、worktree側の .gitattributes を一時的に退避してから --worktree-attributes を付ける必要があります。だんだんめんどくさくなってきました。日常で回せる自信がない・・・!

mv .gitattributes /tmp/gitattributes.bak
git archive --worktree-attributes --format=tar.gz -o /tmp/archive.tar.gz HEAD
mv /tmp/gitattributes.bak .gitattributes

これで、動くには動くんですが .gitattributes が複数階層にあるとその分だけ退避が必要だったり、途中でエラーが起きると戻し忘れる事故が起きそうだったりで、サッと使うには重い方法だなと感じました。

git ls-files を使ったほうが求めているものだった

結局、いろいろやってみたんですが、一番シンプルだったのは git archive を使わない方法でした。

git ls-files です。

git ls-files はそもそも export-ignore を見ないので、これで列挙したファイルをそのまま tar に渡せば全データが取れます。やったね!

git ls-files -z | tar -czf archive.tar.gz --null -T -

-z と --null で NUL 区切りにしているので、ファイル名にスペースや特殊文字が含まれていても安全です。

手元のリポジトリで試したところ export-ignore 指定のファイルも含めて問題なくアーカイブされました!

余談

実は最初 tar じゃなくて zip で固めたのですが、展開先によっては zip を解凍するために追加インストールが必要だったりで、一段手間だったので tar が良いなという感じでした。