3

注:このリポジトリの破損前のクローンはありません。私の状況は、ここで説明されている他の状況とは異なると思います。なぜなら、ブロブではなく、木が欠けているからです。

どうしたの:

LAN経由で(SSH経由で)リポジトリのクローンを作成しようとすると、Gitはリポジトリが破損しているというエラーを返しました。

remote: error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty
remote: fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt
error: git upload-pack: git-pack-objects died with error.
fatal: git upload-pack: aborting due to possible repository corruption on the remote side.
remote: aborting due to possible repository corruption on the remote side.

破損の診断に使用できる場所を見つけましたが、新しいことは何もわかりgit fsckませんでした。

git fsck --full
error: object file ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4 is empty
fatal: loose object 2e223ce259e9e33998d434acc778bc64b393d5d4 (stored in ./objects/2e/223ce259e9e33998d434acc778bc64b393d5d4) is corrupt

リポジトリをローカルで(を使用して--no-hardlinks)複製して何が起こるかを確認しようとしましたが、まったく同じ結果が得られました。

それから私はこの質問に出くわしました、そして答えた人はちょうど空のファイルを削除しました(ステップ3)、それで私はこれをしました(すなわち私は223ce259e9e33998d434acc778bc64b393d5d4サブディレクトリからファイルを削除しましたobjects/2e/)。

git fsckもう一度、そして私は見る:

Checking object directories: 100% (256/256), done.
broken link from    tree 838e437f371c652fa4393d25473ce21cbf697d7a
              to    tree 2e223ce259e9e33998d434acc778bc64b393d5d4
dangling commit 54146bc0dc4eb3eede82a0405b749e05c11c5522
missing tree 2e223ce259e9e33998d434acc778bc64b393d5d4
dangling commit 864864feec207786b84158e526b2faec7799fd4e
dangling blob d3cfd7cc7718d5b76df70cf9865db01c25181bfb

そのため、ツリーに問題があります838e437f37。それは上記の男に起こったことではないので、私はグーグルに行き、Linusからいくつかの情報を見つけました。

それで、私はそうgit ls-tree 838e437f371c652fa4393d25473ce21cbf697d7aしました、そして、出力に次の行がありました:

040000 tree 2e223ce259e9e33998d434acc778bc64b393d5d4    moje

現在、「moje」はディレクトリです(Linusが説明したファイルである例とは異なります)。そういうわけで、Linusによって提案された次のステップがgit hash-object moje返されfatal: Unable to hash mojeました。

とにかく、それが必要なものである可能性はわずかだったので、さらに調べてみました。私が実行git log --raw --all --full-history -- moje/したところ、Linusのガイドによると、2e223を一部のコンテンツのSHA-2ハッシュとしてリストするコミットがあるはずですが、何もありません。そしてリストはで終わります

fatal: unable to read source tree (2e223ce259e9e33998d434acc778bc64b393d5d4)

そのエラーの前にリストされている最後のコミットを調べてみましたが、このハッシュは見つかりませんでした。私はこれを見ましが、おそらく問題のあるバージョンと作業ツリーの現在の状態との間にいくつかの変更があったため、それは私を助けませんでした。

重要なことが1つあります。その中には、Gitリポジトリ自体(サブモジュール)でmoje/あるディレクトリがあります。cli/そこで問題のあるSHA-2ハッシュを探しましたが、見つかりませんでした。

私は何をすべきか?

4

2 に答える 2

6

コマンド(クロニアルが提案)

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi'

は、欠落しているオブジェクトに依存する最初のコミットを返しました2e223ce- その SHA-2 ハッシュは でした499b8fb。その親は問題なく (内容を確認したり、チェックアウトしたりできました)、壊れたコミットの次のコミットもチェックアウトできました ( 89b0fc4)。

ここで、これら 2 つの「適切な」コミット間でどのような変更が行われたかを確認する必要がありました。これは簡単でしたgit diff 499b8fb~ 89b0fc4

diff --git a/somefile b/somefile
deleted file mode 100644
index f5d1e1e..0000000
--- a/somefile
+++ /dev/null
@@ -1,79 +0,0 @@
[ contents of the deleted "somefile"... ]
diff --git a/moje/cli b/moje/cli
index 640a825..c0b1a24 160000
--- a/moje/cli
+++ b/moje/cli
@@ -1 +1 @@
-Subproject commit 640a825cd671dfba83601d6271e7e027665eaca8
+Subproject commit c0b1a24aa246289831ec7db3a8596376db1f625a

somefileこれで、悪いコミットの親と良いコミットの間でファイルが削除され、サブモジュールの HEAD が から640a825に変更されたことがわかりましたc0b1a24。サブモジュール リポジトリに移動し、これら 2 つの間でどのようなコミットが行われたかを尋ねました。

git log --oneline 640a825..c0b1a24

戻った

c0b1a24 <commit message>
8be9433 <commit message>
02564e1 <commit message>

499b8fb~ここで、 と の間で89b0fc4次の 4 つのことが起こっていることがわかりました。

  • somefile削除されました
  • /moje/cliHEAD が から に変更され640a825ました02564e1
  • /moje/cliHEAD が から に変更され02564e1ました8be9433
  • /moje/cliHEAD が から に変更され8be9433ましたc0b1a24

どの部分が499b8fb(悪いコミット) で、どの部分が89b0fc4. しかし幸いなことに、可能性はそれほど多くないので、すべてを試してみました。Git が適切なオブジェクトを計算してデータベースに保存するように、各組み合わせでコミットを行いました。/moje/cliHEAD が にあったときに8be9433git commit不足している2e223ceオブジェクトが作成されたことが判明しました。万歳!

注: 同様の状況にあり、どのコミットが適切で、Git がそれらについて何を教えてくれるかを調べている場合はcheckout、コミットできることと、showそれは 2 つの異なることであることを思い出してください。たとえば、最初はgit show somesha、エラーがスローされた場合、someshaコミットが破損していることを意味し、何にも使用できないと考えていました。git show 89b0fc4それは誤りであることが判明しましgit checkout 89b0fc4git diff 499b8fb~ 89b0fc4

git show someshaこれは、によってどのような変更が導入されたかを示しているためだと思います。そのためsomeshaに、Git は前のコミット (この場合は破損したもの) の内容を読み取る必要があります。どうやら、Git は 1 つをチェックアウトするために以前のコミットを見る必要はありません。

(クロニアルの答えのおかげでこれを行うことができました-彼に称賛を!これを自分の答えとして投稿するように勧められました。)

于 2013-02-14T09:20:24.507 に答える
2

次のコマンドを使用して、欠落しているツリーを含むコミットのリストを取得します。

git rev-list --all | xargs -l -I '{}' sh -c 'if git ls-tree -rt {} > /dev/null 2>&1 ; then true; else git log --oneline -1 {}; git ls-tree -r -t {} | tail -1; fi'

次に、不足しているツリーを再作成する必要があります。そのときとまったく同じコンテンツをそこに配置し、そのツリーをリポジトリに追加します。これを行う最も簡単な方法は、おそらくコンテンツを再作成してからリポジトリにコミットすることです(後でそのコミットを削除できます)。

于 2013-02-12T11:34:57.677 に答える