liuhui998's new blog

using octopress

如何彻底删除 Git 中的提交(commit)

| Comments

如何彻底删除 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

如果想了解更多,可以看看参考资料:)

参考资料:

git gc 英文帮助

git prune 英文帮助

git config 英文帮助

git faq

stack overflow 上资料

Comments