http://liuhui998.com/2010/11/06/remove_commits_completely/
如何徹底刪除 git 中的提交(commit)
原來我寫一博文,說如何如何找回git 中丟失的提交(commit)。當時有人問我,是不是執行
git gc
后那些懸空對象(dangling objects)就被刪了;答案是否定的。
那么是不是這些刪了的東東就不被徹底刪除,就以懸空對象(dangling objects)的形式一直保存系統中的話,那么.git 目錄不就撐爆了;答案也是否定的。
那 git 是如何管理這些懸空對象(dangling objects)的呢?
當我們在執行
git gc
命令時,它會調用
git prune
命令把這些懸空對象(dangling objects)清除掉(prune);一般默認是清除超過二周的懸空對象。如果我們不要等二周時間,可在git 中設置一個環境變量gc.pruneExpire;也可在執行命令時設置清除(prune)的時間長度(expire date)。
下面這條命令就是把當前git倉庫里的所有的懸空對象(dangling objects)都清除:
git gc --prune=0
不過上面這條命令還是不會馬上刪除懸空對象(dangling objects)。因為我們刪除了一個git對象(git object)后,在reflog里還會有記錄的;所以倉庫的懸空對象(dangling objects)還不是真正的懸空對象(dangling objects)。我們只有把reflog中的相關記錄也刪除掉,倉庫中的懸空對象(dangling objects)就沒有任何引用(ref)指向它, git gc –prune=0 才會執行成功。
在執行 git gc 命令時,會清除超過30天的當前head的不可達對象(unreachable)的引用(reflog entries)。如果不想等這么久 ,可以設置gc.reflogexpireunreachable 這個git環境變量,指定expire的時間長度;也可以在命令中設置。
下面這條命令清空了reflog里的所有從當前head不可達對象(unreachable)的引用(reflog entries)。
git reflog expire --expire-unreachable=0 --all
下面的命令展示了如何徹底刪除一個提交對象(commit object)。
rm -rf gitone
mkdir gitone
cd gitone
git init
touch abc
git add abc
git commit -m "abc"
touch bbc
git add bbc
git commit -m "bbc"
touch ccc
git add ccc
git commit -m "ccc"
git reset --hard HEAD^
git fsck --lost-found
sleep 1
git reflog expire --expire-unreachable=0 --all
git gc --prune=0
git fsck --lost-found
后記:
這里最核心的兩個命令就是:
git reflog expire --expire-unreachable=0 --all git gc --prune=0