为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Git
FFIVE 2019-12-04 13:14:23
我在索引中添加了一些文件,但随后错误地使用删除了它们git reset --hard。如何恢复它们?这是发生了什么:我使用添加了所有文件 git add .然后我承诺当我检查状态时,仍然有一些文件未包含在添加的提交中,这很奇怪我再次添加了未跟踪的文件,这次可以正常工作了但是我希望一切都在一次提交中,所以我查看了如何取消刚刚提交的内容我曾经用过git reset --hard HEAD^-不好的主意,显然所有文件都被删除了所以我曾经git reflog找到我离开的地方然后我曾经git reflog ______回到我的最后一次提交。然后我曾经git reset HEAD取消对提交的暂存(本来应该完成的工作),但是提交后添加的文件(参见上文)仍然不存在。如何找回这些文件?
查看完整描述

2 回答

?
萧十郎

TA贡献1815条经验 获得超12个赞

首先,完整备份您的Git存储库!

当您git add创建文件时,git将从该文件的内容中创建一个Blob,并将其添加到其对象数据库(.git/objects/??/*)中。

让我们一一看一下您的命令:

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

$ git add .

这会将当前目录及其子目录中包含的所有文件添加到Git的对象数据库中。.gitignore不会添加文件中与模式匹配的未跟踪文件。树文件也将被写入。请看我答案的结尾。

然后我承诺

$ git commit -m'added all files'

这会将新的提交对象写入对象数据库。该提交将引用一棵树。该树引用Blob(文件)和其他树(子目录)。

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

$ git status

我可以想到发生这种情况的两种情况:在您的文件后面添加了一些修改过的文件或添加了新文件。

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

$ git add .

我假设您add再次使用了与步骤1中相同的命令。

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

我将在此答案的结尾告诉您一种更好的方法,它不需要用户发出潜在的危险 reset

我用了git reset --hard HEAD ^ —坏主意,显然所有文件都被删除了

$ git reset --hard HEAD^

此命令会将您当前的工作树和索引设置为恰好在提交时HEAD^(倒数第二次提交)。换句话说,它将丢弃任何本地未提交的更改,并将分支指针移回一次提交。它不会触摸未跟踪的文件。

所以后来我用git reflog找到我离开的地方

$ git reflog

这将显示最近检出的最后一次提交(与相同git reflog HEAD)。如果您指定分支名称,它将显示该分支最近指向的最后一次提交。

然后我使用git reflog __返回我的上一次提交。

不确定这一点。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 -ugit commit -a它将所有更改转移到跟踪文件中。要跟踪新文件,最好明确地指定它们。


查看完整回答
反对 回复 2019-12-04
?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

我有一个类似的问题,但是我的回购中有很多悬挂的斑点和树木,所以我最终用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


查看完整回答
反对 回复 2019-12-04
  • 2 回答
  • 0 关注
  • 555 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信