2016-12-29 90 views
3

我有一个小的回购有一对夫妇提交的:一个Git复位后,可达承诺不删除

* 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显示被添加的file.txt提交a0fc4f8为未跟踪和文件你好,是由提交f705657加入也显示为未跟踪。
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的节目a0fc4f8仍显示提交

更新3:

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

'git fcck'在'git gc --prune = all'后面说了什么? –

+0

@MichałWalenciak:请检查更新 – Jim

+1

如果您运行'git reset(--mixed)initial',那么您的工作目录是未触及的,这就是为什么'a0fc4f8'提交中有所有更改的原因。 – C1sc0

回答

5

1)否则git show a0fc4f8仍显示提交

这是由设计。不可达的对象不是有几个原因立即删除:

  • 也许你错误地跑了最后的命令(或提供错误的参数给它),你会发现错误,并希望回到以前的状态;
  • 与完成操作所需的工作量相比,删除不可访问的对象(节省一定量的磁盘空间)的收益太小。

修剪不可达对象时会自动执行。它也是由一些git命令执行的(其中一些是fetchpush)。

2)否则git status表明,加入按提交a0fc4f8作为未跟踪和文件被提交f705657加入hellofile.txt也显示为未跟踪。

您运行git reset而没有指定模式。默认模式是--mixed,这意味着:

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

这就解释了为什么文件在目录(第三颗子弹),为什么他们是未经跟踪(第二子弹;该指数相匹配的initial承诺,但在创建时根本不存在这些文件)。

3)运行git gcgit gc --prune=all不会删除a0fc4f8虽然它不是能再连接,并具有与之关联的名称/标签。

git gc还检查分支reflogs的参考。如果您的testbranch分支启用reflog,则reflog中的最新条目指向提交a0fc4f8(这是testbranch分支在运行git reset之前的位置)。您可以通过运行git reflog testbranch来检查分支testbranch是否启用了引用日志。如果它打印了某些内容,则会在第二行的位置[email protected]{1}处找到提交a0fc4f8。表示nth分支name(它指向的提交,n移动过去)的值。

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

节记载:

git gc尝试很难成为它收集垃圾的安全。特别是,它不仅会保存当前一组分支和标记所引用的对象,还会保留由索引引用的对象,远程跟踪分支,由git filter-branch保存在refs/original/中的引用或引用日志(可引用分支中的提交后来修改或倒带)。

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

+0

我在reflog中看到'a0fc4f8',但它不是最近的入口吗?请看更新的OP – Jim

+0

你是对的,这是第二个条目。第一个条目('testbranch @ {0}',最近的)是分支的当前位置。 ['testbranch @ {1}'](https://git-scm.com/docs/gitrevisions#gitrevisions-emltrefnamegtltngtemegemmaster1em)是它以前的位置(即'git reset'移动之前的位置)。 – axiac

+0

因此,如果推荐有一个参考git gc忽略它的东西?但是这意味着git gc永远不会删除提交吗?那个提交不会总是成为reflog历史记录的一部分吗? – Jim