簡體   English   中英

列出和刪除沒有分支的 Git 提交(懸空?)

[英]Listing and deleting Git commits that are under no branch (dangling?)

我有一個 Git 存儲庫,其中包含大量沒有特定分支的提交,我可以git show它們,但是當我嘗試列出包含它們的分支時,它什么也不報告。

我認為這是懸空提交/樹問題(由於 -D 分支),所以我修剪了 repo,但之后我仍然看到相同的行為:

$ git fetch origin

$ git fsck --unreachable
$ git fsck

沒有輸出,沒有任何懸空(對嗎?)。 但是提交存在

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

並且無法通過任何分支訪問,因為

$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042

沒有輸出。

該提交的具體狀態是什么? 如何列出處於相似狀態的所有提交? 我怎樣才能刪除這樣的提交?

要刪除所有懸空提交(包括那些仍然可以從 stash 和其他 reflog 訪問的提交),請執行以下操作:

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

但請確定這是您想要的。 我建議您閱讀手冊頁,但要點如下:

git gc刪除無法訪問的對象(提交、樹、blob(文件))。 如果對象不屬於某個分支的歷史記錄,則該對象是不可訪問的。 實際上它有點復雜:

存儲是使用 reflog 實現的(即不是分支或標簽)。 這意味着它們會受到垃圾收集。

git gc做了一些其他的事情,但它們在這里不相關,也不危險。

兩周內無法訪問的對象不會被刪除,因此我們使用--prune=now表示“刪除之前創建的無法訪問的對象”。

也可以通過 reflog 訪問對象。 分支記錄了某個項目的歷史,而引用日志記錄了這些分支的歷史。 如果您修改、重置等,提交會從分支歷史記錄中刪除,但 git 會保留它們,以防您意識到自己犯了錯誤。 Reflogs 是一種方便的方法來找出在分支(或 HEAD)上執行了哪些破壞性(和其他)操作,從而更容易撤消破壞性操作。

因此,我們還必須刪除 reflogs 才能真正刪除從分支中無法訪問的所有內容。 我們通過使--all reflogs 過期來做到這一點。 git 再次保留一些 reflogs 來保護用戶,所以我們必須再次告訴它不要這樣做: --expire-unreachable=now

由於我主要使用 reflog 來從破壞性操作中恢復,因此我通常使用--expire=now代替,它會完全破壞 reflog。

沒有輸出,沒有任何懸空(對嗎?)

請注意,從您的 reflog 中引用的提交被認為是可訪問的。

該提交的具體狀態是什么? 如何列出具有相似狀態的所有提交

傳遞--no-reflogs以說服git fsck向您展示它們。

我怎樣才能刪除這樣的提交?

一旦您的 reflog 條目過期,這些對象也將被git gc清理。

到期由gc.pruneexpiregc.reflogexpiregc.reflogexpireunreachable設置控制。 參照。 git help config

默認值都非常合理。

在遵循此線程中的所有建議之后,我仍然遇到了同樣的問題:

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>刪除了標簽並重新進行了清理,舊的提交就消失了。

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>訪問。 這是因為它的分離/懸空“分支”中的一個提交被標記了。 我刪除了標簽,再次運行上述命令,我很成功。 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>默認修剪兩周前的對象。 您可以設置一個更新的日期。 但是,創建松散對象的 git 命令通常會運行 git gc --auto (如果松散對象的數量超過配置變量 gc.auto 的值,它會修剪松散對象)。

您確定要刪除這些提交嗎? gc.auto 的默認設置將確保松散對象不會占用不合理的內存量,並且將松散對象存儲一段時間通常是一個好主意。 這樣,如果您明天意識到您刪除的分支包含您需要的提交,您可以恢復它。

如果存儲確實是“不存在”而不是標簽的存儲,
git fsck --full
可能會有所幫助。 當沒有其他解決方案時,它對我有用。

Git:Remove broken stash比這個線程更准確地描述了我的問題)

我知道這不是一個好的解決方案,但我做了一個filter-branch並最終得到了不屬於任何分支但無法自動刪除的重復的、無法訪問的提交,我嘗試了這里發布的每一個解決方案,絕對沒有任何效果. 所以我推送到一個遠程存儲庫(github),刪除了我的本地存儲庫,然后再次拉出並擺脫了所有那些無法訪問的提交

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM