最初に次のコマンドを試してください (必要に応じて再実行してください)。
$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase
それでも問題が解決しない場合は、次のことを試してください。
破損したオブジェクトをすべて削除します。たとえば、
fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
$ rm -v .git/objects/06/91c5...51e5
空のオブジェクトをすべて削除します。
error: object file .git/objects/06/91c5...51e5 is empty
$ find .git/objects/ -size 0 -exec rm -vf "{}" \;
次の方法で「リンク切れ」メッセージを確認します。
git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
これにより、破損したブロブがどのファイルから来たかがわかります!
ファイルを回復するには、本当に幸運かもしれません。それは、作業ツリーで既にチェックアウトしたバージョンである可能性があります。
git hash-object -w my-magic-file
不足している SHA1 (4b945..) が出力された場合は、これですべて完了です。
壊れたのが古いバージョンであると仮定すると、それを行う最も簡単な方法は次のとおりです。
git log --raw --all --full-history -- subdirectory/my-magic-file
これにより、そのファイルのログ全体が表示されます (ツリーが最上位ツリーではない可能性があることに注意してください。そのため、自分でどのサブディレクトリにあったかを把握する必要があります)。 hash-object を持つオブジェクトが再び見つかりません。
コミット、ツリー、またはブロブが欠落しているすべての参照のリストを取得するには:
$ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
通常の branch -d または tag -d コマンドを使用してこれらの ref の一部を削除することはできない場合があります。git が破損に気付くと、これらの ref は削除されるからです。そのため、代わりに配管コマンド git update-ref -d $ref を使用してください。ローカル ブランチの場合、このコマンドは古いブランチ構成を .git/config に残す可能性があることに注意してください。手動で削除できます ([branch "$ref"] セクションを探します)。
すべての参照がクリーンになった後でも、壊れたコミットが reflog に残っている可能性があります。git reflog expire --expire=now --all を使用して、すべての reflog をクリアできます。すべての reflog を失いたくない場合は、個々の ref で壊れた reflog を検索できます。
$ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
(git rev-list に追加された -g オプションに注意してください。) 次に、それぞれに git reflog expire --expire=now $ref を使用します。壊れた参照と参照ログがすべてなくなったら、リポジトリがクリーンであることを確認するために git fsck --full を実行します。ぶら下がっているオブジェクトは問題ありません。
以下に、賢明に使用しないと git リポジトリのデータが失われる可能性があるコマンドの高度な使用法を示します。そのため、誤って git にさらに損害を与える前にバックアップを作成してください。自分が何をしているのかわかっている場合は、自分の責任で試してください。
フェッチ後に上流のブランチの上に現在のブランチをプルするには:
$ git pull --rebase
新しいブランチをチェックアウトして、古いブランチを削除することもできます:
$ git checkout -b new_master origin/master
削除するために git で破損したオブジェクトを見つけるには、次のコマンドを試してください。
while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done
OSX の場合は、sed -E
代わりに を使用しsed -r
ます。
他のアイデアは、pack ファイルからすべてのオブジェクトをアンパックして、.git/objects 内のすべてのオブジェクトを再生成することです。そのため、リポジトリ内で次のコマンドを実行してみてください。
$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak
上記で問題が解決しない場合は、別のリポジトリから git オブジェクトを rsync またはコピーしてみてください。
$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects
次のように、チェックアウトしようとしたときに壊れたブランチを修正するには:
$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625
それを削除して、上流から再度チェックアウトしてみてください。
$ git branch -D master
$ git checkout -b master github/master
git によって切り離された状態になった場合は、 をチェックアウトmaster
して、切り離されたブランチにマージします。
もう 1 つのアイデアは、既存のマスターを再帰的にリベースすることです。
$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master
以下も参照してください。