git重置后,无法删除的提交未删除 [英] After a git reset, unreachable commit not removed

查看:97
本文介绍了git重置后,无法删除的提交未删除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小型仓库,其中有几个提交:

I have a small repo that has a couple of commits:

* 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
我现在看到了:

I can not understand the following behavior. On this state I run: $ git reset initial
I see now:

* 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 gc git gc --prune = all 不会删除a0fc4f8,尽管它不再可访问并且没有名称/标签与之关联.
为什么会这样?

What I was expecting: Commit a0fc4f8 would be deleted since it is unreachable.
What happened:
1) Doing git show a0fc4f8 still shows the commit
2) Doing git status shows the file.txt that was added by commit a0fc4f8 as untracked and file hello that was added by commit f705657 also shows up as untracked.
3) Running git gc or git gc --prune=all does not delete a0fc4f8 although it is not reachable anymore and has no name/tag associated with it.
Why are these happening?

更新:

$ 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仍然显示提交

$ git show a0fc4f8 Still shows the commit

更新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)进行 git show a0fc4f8 仍显示提交

这是设计使然.由于以下几种原因,无法立即删除无法访问的对象:

This is by design. The unreachable objects are not removed immediately for several reasons:

  • 也许您是错误地运行了最后一条命令(或为其提供了错误的参数),您意识到了该错误并想回到先前的状态; <​​/li>
  • 与完成操作所需的工作量相比,删除无法访问的对象(节省一些磁盘空间)的收益太小了.

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

Pruning the unreachable object is performed automatically from time to time. It is also performed by some git commands (fetch and push are some of them).

2)执行 git status 会显示 file.txt ,该文件是由提交 a0fc4f8 作为未跟踪添加的,并且是文件 hello f705657 添加的code>也显示为未跟踪.

2) Doing git status shows the file.txt that was added by commit a0fc4f8 as untracked and file hello that was added by commit f705657 also shows up as untracked.

您在未指定 git reset >模式.默认模式是-mixed ,表示:

You ran git reset without specifying a mode. The default mode is --mixed and that means:

  • 将分支移动到命令中指定的提交(在本例中为 initial );
  • 重置索引以匹配分支所指向的新提交;
  • 未修改工作树.

这说明了为什么文件在目录中(第三个项目符号)以及为什么未对其进行跟踪(第二个项目符号;索引与 initial 提交匹配,但这些文件甚至在存在时都不存在)已创建).

This explains why the files are in the directory (the third bullet) and why they are untracked (the second bullet; the index matches the initial commit but these files didn't even exist when it was created).

3)运行 git gc git gc --prune = all 不会删除 a0fc4f8 ,尽管它不再可访问并且没有与之关联的名称/标签.

3) Running git gc or git gc --prune=all does not delete a0fc4f8 although it is not reachable anymore and has no name/tag associated with it.

git gc 还会检查分支reflog中是否有引用.如果您的 testbranch 分支具有 reflog 启用,然后引用日志中的最新条目指向提交 a0fc4f8 (这是运行 git reset 之前 testbranch 分支的位置).您可以通过运行 git reflog testbranch 来检查是否为分支 testbranch 启用了reflog.如果它打印出一些内容,您将在第二行的位置 testbranch @ {1} 处找到提交 a0fc4f8 .符号 name @ {n} 表示分支 name n th 值(指向的提交, n 过去移动).

git gc also checks the branch reflogs for references. If your testbranch branch has the reflog enabled then the most recent entry in the reflog points to commit a0fc4f8 (this is where the testbranch branch was before you ran git reset). You can check if the reflog is enabled for branch testbranch by running git reflog testbranch. If it prints something you'll find the commit a0fc4f8 on the second line, at position testbranch@{1}. The notation name@{n} means the prior nth value of branch name (the commit it was pointing to, n moves in the past).

您可以找到有关 git gc 方式的更多信息可在文档中使用.

You can find more about the way git gc works in the documentation.

注释 部分中,内容为:

In the Notes section it reads:

git gc 尽力确保其收集的垃圾安全.特别是,它将不仅保留当前分支和标签集引用的对象,还保留索引,远程跟踪分支以及中的 git filter-branch 保存的引用所引用的对象refs/original/或reflog(可以引用分支中的提交,这些分支后来被修改或倒回).

git gc tries very hard to be safe about the garbage it collects. In particular, it will keep not only objects referenced by your current set of branches and tags, but also objects referenced by the index, remote-tracking branches, refs saved by git filter-branch in refs/original/, or reflogs (which may reference commits in branches that were later amended or rewound).

如果您希望收集某些对象,而没有收集到这些对象,请检查所有这些位置,然后决定删除这些引用是否对您有意义.

If you are expecting some objects to be collected and they aren’t, check all of those locations and decide whether it makes sense in your case to remove those references.

这篇关于git重置后,无法删除的提交未删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆