Gitのfatal: loose object *** is corruptを解決する

追記

エラーになったリポジトリの.gitディレクトリをまるっと削除して、ほかでcloneしたリポジトリの.gitディレクトリのみをコピーしてくればいいという話を聞いてなるほどだった。

よって以下の話はほぼ意味ないです。


いつも通り作業しようとしたら以下のようなエラーが出てきた。

error: object file .git/objects/8b/8fb4883de4ebb919bb3bac3b1fb2994d337e1a is empty
error: object file .git/objects/8b/8fb4883de4ebb919bb3bac3b1fb2994d337e1a is empty
error: object file .git/objects/8b/8fb4883de4ebb919bb3bac3b1fb2994d337e1a is empty
error: object file .git/objects/8b/8fb4883de4ebb919bb3bac3b1fb2994d337e1a is empty
fatal: loose object 8b8fb4883de4ebb919bb3bac3b1fb2994d337e1a (stored in .git/objects/8b/8fb4883de4ebb919bb3bac3b1fb2994d337e1a) is corrupt

とりあえず初回はエラーを起こしたローカルリポジトリを横にのけてgit cloneしなおして解決したが、2日連続で出たので以下を参考にしつつ解決法を探る。

参考: Gitのエラーを直そう object is empty →refs/remotes/origin/master does not point to a valid object!

まず.git/objects以下にemptyなファイルができているのが元凶。
なぜそうなったのかは謎である。やや気持ち悪いが復活させようもないので削除する。

find .git -type f -empty -delete

すると以下のようにエラーが変わる。

fatal: bad object HEAD

8fb4883de4ebb919bb3bac3b1fb2994d337e1aがHEADだったので、それがなくなれば、それはそれでエラーになるというわけ。
とりあえず生きているとこまでHEADに戻すために履歴を見る。

tail -n 2 .git/logs/refs/heads/master
8b8fb4883de4ebb919bb3bac3b1fb2994d337e1a 14a7a907eba18e799ec258299f65b5349b829cdb akahige <akahigeg@gmail.com> 1634602786 +0900

14a7a907eba18e799ec258299f65b5349b829cdbが前のHEADなのでそこを参照するようにする。

git update-ref HEAD 
14a7a907eba18e799ec258299f65b5349b829cdb

これでエラーはなくなった。

しかし整合性は回復するが最新のコミットがなかったことになるので、ローカルのリポジトリの状態はまだ完全ではない。
リモートのリポジトリよりpullして最新の状態にする。

git pull

ヨシ!

ただgit statusしてみるとすると差分が発生しているので何かと思ったら、ローカルのファイルのいくつかが空になっている。
.git/objects以下のファイルがemptyになってたのと根っこが同じっぽいなあ。

うーん。WLS上のUbuntuでの出来事なので、原因はそのあたりなのかなあ。

とりあえず

git checkout -- .

で空に変更されたファイルを元に戻して解決。

翌日、3日連続で起きないだろうな、と思いつつPCを立ち上げたけどひとまずは大丈夫だった。

なおこの問題の対処は結局のところエラーになったローカルリポジトリを捨ててgit cloneしなおすのが手っ取り早いと思うが、今回のリポジトリは静的サイト生成したものをs3 syncしてるリポジトリなので、cloneしなおすと全部同期しなおされてつらいということでこういう解決手段を取った。

s3 syncはファイルのタイムスタンプで同期対象を見てるので、内容が同じでもタイムスタンプが変わると同期されちゃうんだよね。チェックサムで見るオプションもないし。

そういうわけでcloneしなおすと少しめんどくさいことがあるよというケースでの回復手段でした。