Gitリポジトリには、特定のブランチの下にない多くのコミットがあり、git show
それらが、それらを含むブランチをリストしようとすると、何も報告しません。
これは(-Dブランチの結果として)コミット/ツリーの問題だと思ったので、レポを削除しましたが、その後も同じ動作が見られます:
$ git fetch Origin
$ git fsck --unreachable
$ git fsck
出力なし、ぶら下がりなし(右?)しかし、コミットは存在します
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
そして、どのブランチからも到達できません
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
出力しません。
そのコミットの状態は正確に何ですか?同様の状態のすべてのコミットを一覧表示するにはどうすればよいですか?このようなコミットを削除するにはどうすればよいですか?
出力なし、ぶら下がりなし(右?)
Reflogから参照されたコミットは到達可能と見なされることに注意してください。
そのコミットの状態は正確に何ですか?同様の状態のすべてのコミットを一覧表示するにはどうすればよいですか
パス --no-reflogs
納得させる git fsck
表示します。
このようなコミットを削除するにはどうすればよいですか?
Reflogエントリの有効期限が切れると、これらのオブジェクトはgit gc
。
有効期限はgc.pruneexpire
、gc.reflogexpire
、およびgc.reflogexpireunreachable
設定。 Cf. git help config
。
デフォルトはすべて非常に合理的です。
未解決のコミットとreflogから到達可能なコミットをすべて削除するには、次のようにします。
git reflog expire --expire-unreachable=now --all
git gc --Prune=now
しかし、これがあなたが望むものであることを確実にしてください。 manページを読むことをお勧めしますが、ここに要点があります。
git gc
到達不能オブジェクト(コミット、ツリー、ブロブ(ファイル))を削除します。オブジェクトは、ブランチの履歴の一部ではない場合、到達不能です。実際には少し複雑です:
git gc
は他にもいくつかのことを行いますが、ここでは関係がなく、危険ではありません。
2週間未満の到達不能オブジェクトは削除されないため、--Prune=now
を使用します。これは、「今までに作成された到達不能オブジェクトを削除する」ことを意味します。
Reflogを介してオブジェクトに到達することもできます。ブランチは一部のプロジェクトの履歴を記録しますが、reflogsはこれらのブランチの履歴を記録します。修正、リセットなどを行うと、コミットはブランチ履歴から削除されますが、間違いを犯したことに気付いた場合に備えてgitはそれらを保持します。 reflogは、ブランチ(またはHEAD)で実行された破壊的な(およびその他の)操作を見つけるための便利な方法であり、破壊的な操作を簡単に取り消すことができます。
したがって、実際にブランチから到達できないものをすべて削除するには、reflogsも削除する必要があります。 --all
reflogsを期限切れにすることでこれを行います。繰り返しますが、gitはユーザーを保護するためにreflogを少し保持しているので、再度そうしないように指示する必要があります:--expire-unreachable=now
。
私は主にreflogを使用して破壊的な操作から回復するため、代わりに--expire=now
を使用します。これは、reflogを完全に圧縮します。
このスレッドのすべてのアドバイスに従った後、私は同じ問題を抱えていました:
git reflog expire --expire-unreachable=now --all
git gc --Prune=now
git fsck --unreachable --no-reflogs # no output
git branch -a --contains <commit> # no output
git show <commit> # still shows up
Reflogでもブランチでもない場合は、...a tag!でなければなりません。
git tag # showed several old tags created before the cleanup
git tag -d <tagname>
のタグを削除し、クリーンアップをやり直したところ、古いコミットはなくなりました。
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
おそらくちょうどする必要があります
git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042
リモートからのブランチについても報告する
同様の問題がありました。 git branch --contains <commit>
を実行しましたが、質問のような出力は返されませんでした。
しかし、実行した後でも
git reflog expire --expire-unreachable=now --all
git gc --Prune=now
git show <commit>
を使用してコミットにアクセスできました。これは、切り離された/ぶら下げられた「ブランチ」のコミットの1つがタグ付けされたためです。タグを削除し、上記のコマンドを再度実行しました。 git show <commit>
が返したfatal: bad object <commit>
-まさに必要なもの。うまくいけば、これは私と同じように動けなかった他の誰かを助けます。
偶然同じ状況に陥り、スタッシュに到達不能なコミットへの参照が含まれていることがわかりました。そのため、推定到達不能コミットはスタッシュから到達可能でした。
これらは本当に到達不能にするために私がしたことでした。
git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --Prune=now
git gc --Prune=<date>
は、デフォルトで2週間前より古いオブジェクトをプルーニングします。より新しい日付を設定できます。ただし、一般にルーズオブジェクトを作成するgitコマンドは、git gc --auto(その数が構成変数gc.autoの値を超えるとルーズオブジェクトをプルーニングします)を実行します。
これらのコミットを削除してもよろしいですか? gc.autoのデフォルト設定は、ゆるいオブジェクトが不当な量のメモリを消費しないことを保証します。また、ゆるいオブジェクトを一定期間保存することは一般に良い考えです。そうすれば、削除したブランチに必要なコミットが含まれていることを明日に気づいた場合、それを回復できます。