On Fri, 9 Nov 2007, Yossi Leybovich wrote:
>
> リポジトリはこのオブジェクトを探すの助けになりませんか?
> このオブジェクトを追跡して、どのファイルがそうであるかを理解するにはどうしたらよいか、誰か知っていますか

つまり、SHA-1ハッシュが暗号的に安全であるという理由だけで、ハッシュ自体は実際には何も教えてくれません。 破損したオブジェクトを修正するには、基本的にその「元のソース」を見つける必要があります。

これを行う最も簡単な方法は、ほとんどの場合、バックアップを作成し、同じオブジェクトを別の場所で見つけることです。 バックアップは本当に良い考えであり、Gitを使用すると非常に簡単になります(他に何もない場合は、リポジトリを別の場所に複製し、ハードリンクされたクローンを使用しないようにします。できれば同じ ディスク/マシン を使用し無いでください)。

しかし、あなたには現在バックアップがないように思われます。しかし、幸いなことに、特に1つのブロブが破損している場合には、これらはある程度デバッグ可能です。

まず、破損したオブジェクトを移動して「保存」します。 これまでの破損の最も一般的な原因はメモリの腐敗でしたが、それでも、破損を見たいと思う人がいます。 しかし、基本的に元のオブジェクトを見るまでは、破損を判断することはできませんので、今は破損したオブジェクトは役に立ちませんが、将来的には破損していないバージョンを再作成できることを期待すると、それは非常に興味深い代物です。

So:

> ib]$ mv .git/objects/4b/9458b3786228369c63936db65827de3cc06200 ../

これは正しいことですが、通常は完全なSHA-1名で保存するのが最善です(あなたは結果から 4b を落としてしまっただけです)。

それが私たちに何を伝えているか見てみましょう:

> ib]$ git-fsck --full
> broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
>              to    blob 4b9458b3786228369c63936db65827de3cc06200
> missing blob 4b9458b3786228369c63936db65827de3cc06200

ええ、私は「dangling commit」(宙ぶらりんコミット)のメッセージを削除しました。これは、おそらくリベースしたという事実に関するメッセージであり、全然面白くありません。 しかし、残っているものはまだ非常に便利です。 特に、どのツリーがそれを指しているかがわかりました。

いまやあなたは以下のようにすることができます

git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8

これは以下のようなものをが表示します

100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8    .gitignore
100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883    .mailmap
100644 blob ca442d313d86dc67e0a2e5d584b465bd382cbf5c    COPYING
100644 blob ee909f2cc49e54f0799a4739d24c4cb9151ae453    CREDITS
040000 tree 0f5f709c17ad89e72bdbbef6ea221c69807009f6    Documentation
100644 blob 1570d248ad9237e4fa6e4d079336b9da62d9ba32    Kbuild
100644 blob 1c7c229a092665b11cd46a25dbd40feeb31661d9    MAINTAINERS
...

そして、以下のような行が表示されます

10064 blob 4b9458b3786228369c63936db65827de3cc06200     my-magic-file

この出力により、あなたには、破損したブロブがどのファイルから発生したかがわかりました!

さて、とはいえまだ十分ではありません。これはファイルのどの「バージョン」が正しく書かれなかったかを教えてくれません! あなたの運が良ければ、すでに作業ツリーでチェックアウトしているバージョンかもしれません。その場合この問題を修正することは本当に簡単です。ただ以下のようにするだけです

git hash-object -w my-magic-file

繰り返しになりますが、欠落分のSHA-1(4b945..)が出力された場合は、これですべて完了です!

しかし、これは本当に幸運なケースでして、今回壊れたのは古いバージョンだったとしましょう。 あなたは、それがどのバージョンだったかをどうやって見分ければよいのでしょうか?

それを行う最も簡単な方法が以下です

git log --raw --all --full-history -- subdirectory/my-magic-file

これにより、そのファイルのログ全体が表示されます(あなたが持っていたツリーはトップレベルのツリーではないかもしれないことを理解してください、それであなたはそれがどのサブディレクトリにあったかをあなた自身で理解する必要があります)。生の出力を要求しているため、以下のようなものが得られます

commit abc
Author:
Date:
  ..
:100644 100644 4b9458b... newsha... M  somedirectory/my-magic-file
commit xyz
Author:
Date:
  ..
:100644 100644 oldsha... 4b9458b... M   somedirectory/my-magic-file

これにより、実際に、そのファイルの「その前のバージョン」と「その次のバージョン」が何であったかを教えてくれるのです! これで、これら(それぞれ「oldsha」と「newsha」)を確認できます。また、あなたはコミットを頻繁に実行し、古いバージョンと新しいバージョンを確認することで、欠落しているmy-magic-fileバージョンを再作成できることを願っています!

これができれば、あなたは不足しているオブジェクトを以下のように再作成できます

git hash-object -w <recreated-file>

これで、あなたのリポジトリは再び良好になります!

(ちなみに、あなたはfsckを無視する事もでき、その場合は以下のように始めます

git log --raw --all

こうやれば、あなたは、全体の中で欠けているオブジェクトのsha(4b9458b..)を探すだけです。ええ、どうやるかはあなた次第です。 Gitは多くの情報を持っていて、ある特定のブロブのバージョンが欠けているだけなのです。

ツリー、特にコミットを再作成しようとすると、はるかに困難になります。 だから今回ブロブであることは幸運でした。 コレなら再作成できる可能性は十分にあります。

Linus