恢复添加到索引但又被git reset删除的文件

我在索引中添加了一些文件,但随后错误地使用删除了它们git reset --hard。如何恢复它们?这是发生了什么:

  1. 我使用添加了所有文件 git add .

  2. 然后我承诺

  3. 当我检查状态时,仍然有一些文件未包含在添加的提交中,这很奇怪

  4. 我再次添加了未跟踪的文件,这次可以正常工作了

  5. 但是我希望一切都在一次提交中,所以我查看了如何取消刚刚提交的内容

  6. 我曾经用过git reset --hard HEAD^-不好的主意,显然所有文件都被删除了

  7. 所以我曾经git reflog找到我离开的地方

  8. 然后我曾经git reflog ______回到我的最后一次提交。

  9. 然后我曾经git reset HEAD取消对提交的暂存(本来应该完成的工作),但是提交后添加的文件(参见上文)仍然不存在。

如何找回这些文件?


FFIVE
浏览 558回答 2
2回答

萧十郎

首先,完整备份您的Git存储库!当您git add创建文件时,git将从该文件的内容中创建一个Blob,并将其添加到其对象数据库(.git/objects/??/*)中。让我们一一看一下您的命令:我使用git add添加了所有文件。$&nbsp;git&nbsp;add&nbsp;.这会将当前目录及其子目录中包含的所有文件添加到Git的对象数据库中。.gitignore不会添加文件中与模式匹配的未跟踪文件。树文件也将被写入。请看我答案的结尾。然后我承诺$&nbsp;git&nbsp;commit&nbsp;-m'added&nbsp;all&nbsp;files'这会将新的提交对象写入对象数据库。该提交将引用一棵树。该树引用Blob(文件)和其他树(子目录)。当我检查状态时,仍然有一些文件未包含在添加的提交中,这很奇怪$&nbsp;git&nbsp;status我可以想到发生这种情况的两种情况:在您的文件后面添加了一些修改过的文件或添加了新文件。我再次添加了未跟踪的文件,这次可以正常工作了$&nbsp;git&nbsp;add&nbsp;.我假设您add再次使用了与步骤1中相同的命令。但是我希望一切都在一次提交中,所以我查看了如何取消刚刚提交的内容我将在此答案的结尾告诉您一种更好的方法,它不需要用户发出潜在的危险&nbsp;reset我用了git reset --hard HEAD ^ —坏主意,显然所有文件都被删除了$&nbsp;git&nbsp;reset&nbsp;--hard&nbsp;HEAD^此命令会将您当前的工作树和索引设置为恰好在提交时HEAD^(倒数第二次提交)。换句话说,它将丢弃任何本地未提交的更改,并将分支指针移回一次提交。它不会触摸未跟踪的文件。所以后来我用git reflog找到我离开的地方$&nbsp;git&nbsp;reflog这将显示最近检出的最后一次提交(与相同git reflog HEAD)。如果您指定分支名称,它将显示该分支最近指向的最后一次提交。然后我使用git reflog&nbsp;__返回我的上一次提交。不确定这一点。git reflog(大多数情况下)是只读命令,不能用于“找回”提交。您只能使用它来查找提交HEAD指向的分支(或)。然后我用git reset HEAD取消了提交的阶段(本来应该做的),但是提交之后我添加的文件(见上文)仍然消失了。$ git reset HEAD这不会取消暂存此提交,但会取消暂存索引中所有已暂存(但未提交)的更改。最初(第一步),您想说git reset HEAD^(或git reset --mixed HEAD^)–这将使您的工作树保持不变,但是将索引设置为匹配由命名的提交所指向的树HEAD^。现在,要取回文件,您必须使用git fsck --full --unreachable --no-reflog。它将扫描Git对象数据库中的所有对象并执行可达性分析。您要寻找blob对象。还应该有一个tree对象,描述第二秒钟后的状态git add .git cat-file -p <object hash>将打印文件内容,因此您可以验证是否具有正确的对象。对于Blob,您可以使用IO重定向将内容写入正确的文件名。对于树,您必须使用git命令(git read-tree)。如果只有几个文件,最好将它们直接写入文件。这里有几点注意事项:如果要向最后一次提交中添加文件(或编辑其提交消息),则可以简单地使用git commit --amend。基本上是一个包装git reset --soft HEAD^ && git commit -c HEAD@{1}。而且,使用它绝不是一个好主意git add .。通常,在创建新存储库时,您只想在第一次使用它。更好的替代方法是git add -u,git commit -a它将所有更改转移到跟踪文件中。要跟踪新文件,最好明确地指定它们。

翻翻过去那场雪

我有一个类似的问题,但是我的回购中有很多悬挂的斑点和树木,所以我最终用grep所有悬挂的斑点的输出进行过滤,并打印出匹配的斑点。假设${UNIQUE_CODE}有一些代码对于索引中的文件是唯一的,那么这应该为您提供要查找的斑点的哈希值:for b in $(git fsck --lost-found | grep blob | awk '{print $3}'); do git cat-file -p $b | grep -q ${UNIQUE_CODE} && echo $b; done
打开App,查看更多内容
随时随地看视频慕课网APP