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 が良いなという感じでした。