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を使う場合は注意が必要です。