MacでRailsプロジェクトをtarで固め、WSL(Linux)環境で展開し、bundle update を実行したところ、以下のようなエラーに遭遇しました。
error: index file .git/objects/pack/._pack-xxxxxxxx.idx is too small
一見するとGitのpackファイルが壊れたように見えますが、原因はGitではなく、macOS特有のファイル仕様にあった模様です。
原因:macOSの ._* ファイル(AppleDouble)
原因は、エラーメッセージに含まれている、ファイル名から推測することができます。
._pack-xxxxxxxx.idx
._ で始まるファイルは、macOSが自動生成する補助ファイルです。
macOSはファイルに拡張属性(xattr)、Finder情報、リソースフォークなど、POSIXに収まらない情報を持たせることができます。LinuxやWSLはこれを理解できないため、別ファイル(._filename)として情報を退避します。これがAppleDoubleファイルです。
なぜ Git が壊れるのか
Gitは.git/objects/pack/*.idx をpack indexファイルとして扱います。
しかし._pack-xxxx.idxは中身がほぼ空で、サイズも異常に小さく、Gitの正規pack indexファイルではありません。このためファイルが壊れていると判断されるのです。
ちなみにMac同士の場合は、._*ファイルがあっても適切に扱われるため問題が発生しません。MacからLinux(WSL含む)など他のOSに持ち込んだ場合に問題となります。
解決策1: COPYFILE_DISABLE=1 を使う
Macでtar実行する際に以下のように実行します。
COPYFILE_DISABLE=1 tar -czf project.tar.gz project/
COPYFILE_DISABLEは環境変数で、macOS の copyfile 機構に対して「拡張属性を._*に書き出すな」と指示します。これにより余計なファイルが作られず、Linuxで安全に展開できることになります。
解決策2: .gitを除外する
Railsプロジェクトの場合、tarファイルを作成する際に、.gitを除外する方法もあります。
tar --exclude='.git' -czf project.tar.gz project/
コピー先で以下のコマンドを実行すればGit作業を行うことができます。
git init
git remote add origin https://github.com/xxx/yyy.git
git fetch
git checkout -B main origin/main
すでに壊れてしまった場合の応急処置
すでに壊れてしまった場合は、Linux(WSL)側で以下のコマンドを実行します。
find . -name '._*' -delete
その後以下のコマンドを実行します。
bundle update
まとめ
Macでtarコマンドを実行する場合、COPYFILE_DISABLE=1 を指定することでトラブルを防ぐことができます。特にGitを使う場合は注意が必要です。