git重置后,无法删除无法访问的提交

时间:2016-12-29 20:56:17

标签: git git-branch git-reset git-gc

我有一个小的回购,有几个提交:

* a0fc4f8 (HEAD -> testbranch) added file.txt  
* e6e6a8b (master) hello world now  
* f308f53 Made it echo  
* f705657 Added hello  
* 08a2de3 (tag: initial) initial  

另外:

$ git status  
On branch testbranch  
nothing to commit, working directory clean  

我无法理解以下行为。在这种状态下,我运行: $ git reset initial
我现在看到了:

* e6e6a8b (master) hello world now  
* f308f53 Made it echo  
* f705657 Added hello  
* 08a2de3 (HEAD -> testbranch, tag: initial) initial  

我的期望:提交a0fc4f8将被删除,因为它无法访问 发生了什么:
1)执行git show a0fc4f8仍然显示提交
2)执行git status显示通过提交a0fc4f8添加的file.txt为未跟踪,并且由提交f705657添加的文件hello也显示为未跟踪。 3)运行git gcgit gc --prune=all不会删除a0fc4f8,尽管它不再可用,并且没有与之关联的名称/标签。
为什么会发生这种情况?

更新:

$ git fsck  
Checking object directories: 100% (256/256), done.  
Checking objects: 100% (15/15), done.    

更新2:

$ git log --all --decorate --graph --oneline  
* e6e6a8b (master) hello world now  
* f308f53 Made it echo  
* f705657 Added hello  
* 08a2de3 (HEAD -> testbranch, tag: initial) initial  

$ git gc --force  
Counting objects: 15, done.  
Delta compression using up to 4 threads.  
Compressing objects: 100% (8/8), done.  
Writing objects: 100% (15/15), done.   
Total 15 (delta 1), reused 15 (delta 1)   

$ git log --all --decorate --graph --oneline  
* e6e6a8b (master) hello world now  
* f308f53 Made it echo  
* f705657 Added hello  
* 08a2de3 (HEAD -> testbranch, tag: initial) initial  

$ git show a0fc4f8仍显示提交

更新3:

$ git reflog testbranch  
08a2de3 testbranch@{0}: reset: moving to initial  
a0fc4f8 testbranch@{1}: commit: added file.txt  
e6e6a8b testbranch@{2}: branch: Created from HEAD  

1 个答案:

答案 0 :(得分:6)

  

1)做git show a0fc4f8仍然显示提交

这是设计的。由于以下几个原因,不会立即删除无法访问的对象:

  • 也许你错误地运行了最后一个命令(或者提供了错误的参数),你意识到错误并希望回到之前的状态;
  • 与完成操作所需的工作量相比,删除无法访问的对象(节省一些磁盘空间)的收益太小。

不时会自动修剪无法访问的对象。它也是由一些git命令执行的(fetchpush是其中的一部分。)

  

2)执行git status会将提交file.txt添加的a0fc4f8显示为未跟踪,并且提交hello添加的文件f705657也会显示没有跟踪。

您在未指定模式的情况下运行git reset。默认模式为--mixed,表示:

  • 将分支移动到命令中指定的提交(在这种情况下为initial);
  • 重置索引以匹配分支指向的新提交;
  • 工作树未被修改。

这解释了为什么文件在目录(第三个项目符号)中以及它们未被跟踪的原因(第二个项目符号;索引与initial提交相匹配,但这些文件在它不存在时甚至不存在创建)。

  

3)正在运行git gcgit gc --prune=all不会删除a0fc4f8,但它不再可以访问,并且没有与之关联的名称/标记。

git gc还检查分支reflogs以获取引用。如果您的testbranch分支已启用reflog,那么reflog中的最新条目将指向提交a0fc4f8(这是testbranch分支在您运行{{1}之前的位置}})。您可以通过运行git reset来检查是否为分支testbranch启用了reflog。如果它打印了某些内容,您将在第二行的git reflog testbranch位置找到提交a0fc4f8。符号name@{n}表示分支testbranch@{1}的先前n th 值(它指向的提交,name过去移动)。

您可以在git gc找到有关documentation工作方式的更多信息。

Notes 部分中,它显示为:

  

n非常努力地保护它收集的垃圾。特别是,它不仅会保留当前分支和标记集引用的对象,还会保留索引引用的对象,远程跟踪分支,git gcgit filter-branch保存的引用或reflogs(这可能会引用后来修改或重绕的分支机构的提交。)

     

如果您希望收集某些对象而不是这些对象,请检查所有这些位置,并确定在您的情况下删除这些引用是否有意义。