如何恢复被Git删除的文件?

7

我是一个git新手,git刚刚删除了一堆重要文件。我该如何找回它们?

我在本地机器上有一个仓库。为了进入git,我只需右键单击我的项目文件夹,然后选择“git bash here”。这将打开主控台,在那里我进行所有的git操作。

所以我有一些更改需要暂存,我执行了以下操作:

git add .

这个操作引发了一系列的更改。我发现有些更改我并不想要,于是决定尝试将所有更改都撤销。我执行了以下操作:

git reset --hard HEAD^

这基本上删除了我在最后一次提交中创建的一堆文件,并跳转到提交之前。

我该如何找回这些文件?如果不能通过git进行,是否还有其他方法?


可能是与https://dev59.com/2XNA5IYBdhLWcg3wC5Xh重复的问题。 - tanascius
6个回答

10

在我的原始建议方面,我需要更正(请参见编辑历史记录)。作为赎罪,我已经找到了从GIT中恢复您丢失的文件的最简单方法:

git fsck --lost-found
ls .git/lost-found/other

很不幸,文件名已丢失,但内容应该作为不同的文件存在。


1
他使用了 git add . ... 所以他应该能够恢复。 - tanascius
fsck会影响我的repo吗?因为我已经执行了以下操作:git reset --hard {removed head}以恢复一些更改。但我仍然需要找回未提交的更改。 - Ryan
如果您有任何疑虑,可以先使用除git以外的其他工具备份整个repo。但我认为fsck不会造成任何损坏。 - Marcelo Cantos
你不知道你刚刚挽救了我多少时间,避免了一个粗心的手残操作。谢谢! - Brandon Bloom
在某些情况下,git 甚至可以恢复文件名:https://dev59.com/2XNA5IYBdhLWcg3wC5Xh#15472831 - Mikko Rantalainen

1
我知道这是一个老帖子,但我想在这里补充一些内容。
使用后。
$ git fsck --cache --no-reflogs --lost-found --unreachable HEAD

我们得到了数千个文件的列表(就像我的情况一样),看起来不可能手动检查所有的文件,因此我们可以按照任何适合您的方式过滤列表,以仅找到 blob 文件。在我的情况下,我使用 Python 并将 git fsck 的输出从控制台复制到文件中,然后读取该文件以获取行列表。
with open("lost_files.txt") as file:
    lost_files = file.readlines()

然后进行筛选以分离blob类型的内容。
[line.split(' ')[-1].strip() for line in lost_files if "blob" in line]

结果是哈希列表。然后进入控制台并声明一个变量FILES,将上面生成的哈希列表粘贴到这里。FILES=('5c2d8667ef8abbd7e114d2f9b61ee840b034e56f' ....... '6dad86cd9c7a80ff5c3cd1d3222d2f8228dc18cf'),因为有近5000个文件,所以只需在控制台中编写一个简单的循环即可。

for lost_file in "${FILES[@]}"; do   git show  $lost_file > lost/lost_file_$lost_file.txt; done

作为结果,我在丢失的目录中得到了5K个文件。 然后只需打开每个文件并使用grep命令来查找所需数据。 对于我而言,下面是相关脚本(在处理功能时,我试图使用有意义的命名方式,因此我只添加了按关键字过滤的筛选器)。

import os

lost_files_names = os.listdir("lost")
names = []
for file in lost_files_names:
    with open(f"lost/{file}", "rb") as data:
        temp = data.readlines()
    for x in temp:
        if b"my_keyword" in x:
            names.append(file)
for x in set(names):
    print(x)
 

终于,我得到了包含10个文件的输出,并在短时间内成功地恢复了不小心丢失的未提交代码(感谢上帝,我已经使用git add)。


我只是将git fsck的输出从控制台复制到文件中。你熟悉输出重定向吗?如果不熟悉,请了解一下。它是一个很棒的工具,可以使用单个命令完成所有操作,而不必使用鼠标来突出显示和复制文本,然后将其粘贴到编辑器中。 - Code-Apprentice
1
谢谢,我对这个不是很熟悉,但是你说得对,我知道可以只用cmd命令来完成相同的操作,当时我选择了最简单的方式)) - Max Pototskiy

1

从这个SO-Question开始:


你可以(需要一些工作)恢复到最后一次“git add <file>”时文件的状态。你可以使用

$ git fsck --cached --no-reflogs --lost-found --unreachable HEAD

然后检查'.git/lost-found/blob/'目录中的文件。

请阅读git fsck手册:我没有检查上述调用。



1

看起来你想要旧的 HEAD(而不是 HEAD^),在这种情况下,你可以简单地检出那个版本。使用 git reflog 显示之前的 HEAD,并查找你想要的提交,然后检出它。

如果你想要重置前暂存的文件,请参考其他答案。


好的建议-当然,引用日志会帮助恢复最后一次提交...再加上我的fsck解决方案,他应该能够恢复所有文件。 - tanascius

0

不,使用

git reset --hard HEAD^

更改将被还原到上一个提交并永久丢失。


1
他使用了 git add . ... 所以他应该能够恢复。 - tanascius

0
如@tanascius所提到的,您可以使用以下命令来恢复已添加但未提交的文件。此命令会在控制台中打印出对blob和trees对象的SHA-1引用。
$ git fsck --cache --no-reflogs --lost-found --unreachable HEAD

blob对象实际上就是你在使用git reset命令时丢失的文件。使用以下命令来恢复它(实际文件名不幸丢失):

$ git show "<SHA-1 REFERENCE TO THE BLOB OBJECT HERE>" > lost_file.txt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接