ブランチの下にないGitコミットの一覧表示と削除(ぶら下がり?)


146

特定のブランチの下にないコミットがたくさんあるGitリポジトリを持っていますが、git showそれらはできますが、それらを含むブランチを一覧表示しようとすると、何も報告されません。

これは(-Dブランチの結果として)未解決のコミット/ツリーの問題だと思ったので、リポジトリをプルーニングしましたが、その後も同じ動作が見られます。

$ git fetch origin

$ git fsck --unreachable
$ git fsck

出力はなく、ぶら下がっていません(右?)。しかし、コミットは存在します

$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...

そしてそれはどのブランチからも到達できません

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

出力はありません。

そのコミットの状態は正確には何ですか?すべてのコミットを同様の状態で一覧表示するにはどうすればよいですか?このようなコミットを削除するにはどうすればよいですか?


回答:


75

出力はなく、ぶら下がっていません(右?)

reflogから参照されるコミットは到達可能と見なされることに注意してください。

そのコミットの状態は正確には何ですか?同様の状態のすべてのコミットを一覧表示するにはどうすればよいですか

あなたにそれらを示す--no-reflogsために納得させるgit fsckために渡します。

このようなコミットを削除するにはどうすればよいですか?

reflogエントリが期限切れになると、それらのオブジェクトもによってクリーンアップされgit gcます。

有効期限は、によって規制されgc.pruneexpiregc.reflogexpireおよびgc.reflogexpireunreachable設定を行います。Cf. git help config

デフォルトはすべてかなり妥当です。


2
つまり、ダングリングコミットのリフローはしばらくすると自動的に削除されるということですか。
MoralCode、2016年

2
基本的に:はい–質問が少し混乱していることを除いて。私はことを言っているすべての REFLOGエントリはしばらく後に自動的に削除されますが、構成設定によってそれを変更することができます。また、コミットは、参照ログに何も指定されていない場合にのみ宙ぶら下がりと呼ばれるため(reflogエントリを含む)、「ぶら下がりコミットのreflog」は重要ではありません。それらは「到達不能なコミットのreflogs 」になります。
アリストテレスパガルツィス2017

「それらは「到達不能なコミットのreflogs」になります。」しかし、「reflogから参照されたコミットは到達可能と見なされる」と述べました。では、「到達不能なコミットのreflogs」はどのように処理できるのでしょうか。私は困惑している。
LarsH 2018年

1
ええ、私は一貫していませんでした。通常、人々はreflogについて考えません、そして彼らが「到達不可能」と言うとき、それは「refから」を意味します。git help glossaryそれをそのように定義することもできますが、「到達可能」の定義はそのように絞り込まれていないため、矛盾しています。おかしい–だから私が言ったことは、実際のところgitglossary… の混乱と一致しています。混乱を招くのは概念ではなく、単に用語です。重要なのは、「ぶら下がっている」コミットは他にも示していないものだということです。「他の方法では到達できないコミットのreflogs」と私が言った場合、それは役に立ちますか…?
アリストテレスPagaltzis

これはすべて非常に混乱します。簡単にしましょう。ブランチmasterにいるとき、あなたはそうしgit commit、コミットを取得し000001ます。それから、あなたはgit commit --amendコミットし000002ます。タグやブランチを指すタグがなくなったため000001--reflogオプションがないとログに表示されませんが、必要に応じて、でアクセスできますgit checkout 000001。今の質問は、ありですダングリングがコミット、または到達不能両方のコミット、またはどちらか?000001
チャーベイ2018

264

ダングリングコミットと参照ログから到達可能なコミットをすべて削除するには、次のようにします。

git reflog expire --expire-unreachable=now --all
git gc --prune=now

しかし、これがあなたが望むものであることを確認してください。manページを読むことをお勧めしますが、ここに要点があります。

git gc到達できないオブジェクト(コミット、ツリー、ブロブ(ファイル))を削除します。あるブランチの履歴に含まれていないオブジェクトは到達不能です。実際には少し複雑です:

git gc 他のいくつかのことを行いますが、それらはここでは関係なく、危険でもありません。

2週間未満の到達不能オブジェクトは削除されないため、--prune=now「これまでに作成された到達不能オブジェクトを削除する」という意味で使用します。

オブジェクトには、reflogからもアクセスできます。ブランチはいくつかのプロジェクトの履歴を記録しますが、reflogはこれらのブランチの履歴を記録します。修正、リセットなどを行うと、コミットはブランチ履歴から削除されますが、間違いを犯したことに気付いた場合に備えて、gitはそれらを保持します。Reflogは、ブランチ(またはHEAD)で実行された破壊的な(およびその他の)操作を見つけるのに便利な方法であり、破壊的な操作を元に戻すのが簡単になります。

したがって、ブランチから到達できないすべてのものを実際に削除するには、reflogも削除する必要があります。これは、--allreflog を期限切れにすることで行います。ここでもgitはユーザーを保護するためにreflogsを少し保持しているので、再びそうしないように指示する必要があります--expire-unreachable=now

私は主にreflogを使用して、破壊的な操作から回復するので--expire=now、代わりに通常使用します。これにより、reflogが完全に削除されます。


1
どのコマンドを使用するかは明らかではありませんが、GCで十分ではありませんか?知らないうちにgit-reflogを使用したことがない場合。これで、使用する必要のあるコマンドがわかったので、前述のオプションをマニュアルページで検索する必要があります。もちろん、代わりにそこからその情報をコピーすることもできます...
tarsius

1
実際、私はそれが何をするかを正確に言います:「すべてのぶら下がりコミットとreflogから到達可能なコミットを削除してください」。reflogが何かわからない場合:もう一度マニュアルを読んでください。
tarsius 2012

7
与えられた答えは正しいかもしれませんが、@ erikb85は、あなたが何をすべきかについて教育されていなかったことを指摘するのは正しいです。RTFMでフォローアップすることは、あまり役に立ちません。はい、すべてのドキュメントを読む必要があります。場合によっては、検索を行っている人が何が起こっているのかを知るのに十分なドキュメントを理解していないことがあります。したがって、コマンドが何をしているのかについての少しの教育は、後でこの答えを見つけたすべての人に役立ちます。
Lee Saferite 2013年

@LeeSaferiteはあなたが今すべて幸せであることを願っています:-)
tarsius

12
git reflog expire --expire-unreachable=now --allすべての隠し場所を落とします!
Vsevolod Golovanov 2017年

22

私は同じ問題を抱えていましたが、このスレッドのすべてのアドバイスに従ってください:

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でもブランチでもない場合、... タグである必要があります。

git tag                             # showed several old tags created before the cleanup

でタグを削除しgit tag -d <tagname>、クリーンアップをやり直したところ、古いコミットはなくなりました。


タグ(stackoverflow.com/a/37335660/450127)に関する回答はすでにあり、これが新しいことを追加するようには思えません。以前の答えを支持してこれを削除すべきではありませんか?
Ian Dunn

確かに、どういうわけか私はその答えを見過ごしていました。4人が私の回答が役に立ったと思ったので、多分それは役に立たないのではないでしょうか?また、すべての可能性を1つの簡潔な回答にまとめました。
jakub.g 2017年

1
重複している場合でも、このページはGoogleの結果に表示されることがあり、それはすぐにちょうどリンクに何度も何度も人をリダイレクトするよりも良い、同じ問題を持つ人々を助け正しい答えを持っています。
Alexandre T.

14
git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

おそらくちょうどである必要があります

git branch -a --contains 793db7f272ba4bbdd1e32f14410a52a412667042

リモートからのブランチについても報告する


おかげで、今私はまだこのコミットを保持している私のremotes / origin / nextを見つけました。それを削除する方法?git push -d origin next助けにはならない。
iRaS


ありがとう- git fetch --pruneトリックをしました。しかし、すべての回答で、このコミットを参照しているタグのチェックがありません。まだコミットでタグをチェックする方法がわかりません(すべて削除しました)。
iRaS 2018

しかし...これは、リモートブランチからのみ到達可能でローカルブランチからは到達可能でないコミットは到達可能と見なされるためgit fsck --unreachable、実際にはネットワーク経由でリモートと通信して、到達可能なコミットを見つけることを意味しますか?
LarsH

1
私自身の質問に答えました...はい、リモートブランチからのみ到達可能(ローカルブランチは不可)のコミットは到達可能と見なされます。ただし、git fsck --unreachableどのリモートブランチにどのコミットが含まれているかを確認するために、ネットワークを介してリモートと通信する必要はありません。リモートブランチ情報は、eg .git/refs/remotes/origin(またはpacked-refs)の下にローカルに保存されます。
LarsH

8

同様の問題がありました。私が実行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>-まさに私が必要とするもの。うまくいけば、これは私と同じように行き詰まっている他の誰かを助けるでしょう。


どのようにタグを削除しましたか?
18

@baporsすべてのタグをリストし、問題のコミットを参照しているタグを見つけて削除します。stackoverflow.com/questions/5480258/...
アンドリュー・ラーション

4

誤って同じ状況に遭遇し、スタッシュに到達不能コミットへの参照が含まれていることがわかりました。そのため、到達不能コミットの推定はスタッシュから到達可能でした。

これらは、本当に到達不可能にするために私がしたことでした。

git stash clear
git reflog expire --expire-unreachable=now --all
git fsck --unreachable
git gc --prune=now

2

git gc --prune=<date>デフォルトでは、2週間前より古いオブジェクトをプルーニングします。より新しい日付を設定できます。ただし、ルーズオブジェクトを作成するgitコマンドは、一般にgit gc --autoを実行します(これにより、数が構成変数gc.autoの値を超えるとルーズオブジェクトがプルーニングされます)。

これらのコミットを削除してもよろしいですか?gc.autoのデフォルト設定は、ルーズオブジェクトが不当な量のメモリを占有しないことを保証します。ルーズオブジェクトを一定期間保存することは、一般的には良い考えです。そうすることで、削除したブランチに必要なコミットが含まれていることが明日わかった場合、それを回復できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.