如何在Git存储库中查找和恢复已删除的文件?

3192

假设我在一个Git仓库中。我删除了一个文件并提交了这次更改。然后,我继续工作并做出了一些更多的提交。然后,我发现需要恢复之前删除的那个文件。

我知道可以使用git checkout <commit> -- filename.txt命令来检出一个文件,但我不知道何时删除了该文件。

  1. 如何找到删除指定文件的提交?
  2. 如何将该文件恢复回我的工作副本?

43
请注意,前一条评论回答了标题中的问题,而不是正文中的问题——这包括查找文件何时被删除。 - avdgaag
14
查找文件被删除的提交记录:git log --diff-filter=D -- path/to/file - titaniumdecoy
@hhh不起作用,我收到错误消息:pathspec './src/main/resources/file'未匹配任何已知于git的文件。 - kap
64
如果文件已被删除但该删除尚未暂存或提交,使用git checkout deletedFile命令可以恢复该文件。但这并不是本问题所要求的;本问题是关于如何恢复一个在很多次提交之前被删除的文件。 - Mark Amery
显示剩余2条评论
30个回答

19
实际上,这个问题直接与Git有关,但像我这样的人使用GUI工具,如WebStorm VCS,而不是了解Git CLI命令。
我右键单击包含已删除文件的路径,然后转到Git,然后单击显示历史记录

Enter image description here

VCS工具显示所有版本的历程,我可以看到每个版本的提交和更改。

Enter image description here

然后我选择了我朋友删除了PostAd.js文件的提交。现在看下面:

Enter image description here

现在,我能看到我想要恢复的已删除文件。我只需双击文件名即可恢复。

Enter image description here

我知道我的回答不是关于Git命令的,但它对于初学者和专业开发人员来说快速、可靠且易于使用。{{WebStorm}} VCS工具非常棒,非常适合与Git一起使用,而且不需要任何其他插件或工具。

如果您不知道文件被删除在哪个提交中,而且这已经发生了一段时间,那么您将花费很多时间手动查看每个提交。 - Ilya Serbis
1
这很有用,因为我通常不记得我正在寻找的文件的完整路径。 - Eric Majerus

18

git undelete path/to/file.ext

  1. 将以下代码添加到您的 .bash_profile 文件中(或者其他在打开命令行时加载的相关文件):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. 然后使用:

  3. git undelete path/to/file.ext
    
    该别名首先检查文件最后存在的提交,然后从该文件最后存在的提交处检出该文件路径。来源


15
git checkout /path/to/deleted.file

这个对于我的情况来说是最直接的解决方案。 - Paulo Oliveira
1
需要解释一下。 - Peter Mortensen

12

在许多情况下,将coreutils(grep、sed等)与Git结合使用会非常有用。我已经非常熟悉这些工具,但对于Git的了解不够深入。如果我想要搜索一个已删除的文件,我会按照以下步骤操作:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

当我找到修订/提交时:
git checkout <rev>^ -- path/to/refound/deleted_file.c

就像其他人之前所说的一样。

文件现在将被恢复到删除之前的状态。如果您想保留它,请记得重新提交到工作树中。


7

我需要从一个特定的提交中恢复一堆被删除的文件,我使用了两个命令来完成:

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(注意每个命令末尾的空格。)

这些文件已经被添加到.gitignore文件中并通过git rm清除。我需要恢复这些文件,然后取消暂存它们。我有数百个需要恢复的文件,如果像其他示例中那样手动输入每个文件将会太慢。


7

我曾经有同样的问题。在不知情的情况下,我创建了一个悬空提交(dangling commit)

列出悬空提交:

git fsck --lost-found

检查每个悬空提交:

git reset --hard <commit id>

当我转移到悬空提交时,我的文件重新出现了。

运行git status 命令可查看原因:

“HEAD 分离于 <分离的提交 id>”


7

找到删除你的文件的提交:

git log --diff-filter=D --oneline -- path/to/file | cut -f -d ' '

样例输出:
4711174

自Git 2.23版本以来,实际上已经有了一个“restore”命令。虽然它仍然是实验性的,但如果要恢复您在提交中删除的内容(在此情况下为4711174),则可以输入以下命令:
git restore --source=4711174^ path/to/file

请注意在提交ID后的^,因为我们希望从删除该文件的提交之前的提交中恢复某些内容。 --source参数告诉restore命令在哪里查找要还原的文件,可以是任何提交,甚至是索引。
参见:git 2.23.0的git-restore文档

3
谢谢。我的cut命令需要不同的参数。在MacOS 10.13.6和Git 2.26中使用以下命令:git log --diff-filter=D --oneline -- path/to/file | cut -d ' ' -f 1 - Minimul

5
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull 
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

恢复已删除的文件:

user@bsd:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
user@bsd:~/work/git$ git checkout slides.tex 
user@bsd:~/work/git$ ls slides.tex
slides.tex

2
这个问题是关于在文件被删除并提交更改后如何恢复文件。而这个答案则是关于如何恢复仅在工作目录中被删除的文件。 - akaihola
1
没错,那就是我在寻找的。 - Hola Soy Edu Feliz Navidad

5

优点:以下方法适用于即使文件/文件夹已从您的垃圾箱或回收站中删除的场景。

文件/文件夹已从工作树中删除,但尚未提交:

I. 如果您尚未索引(git add)您的更改,您可以还原目录的内容:

git restore -- path/to/folder_OR_file

II. 如果删除已被索引,您应该首先重置它:

git reset -- path/to/folder_OR_file

然后执行 git restore path/to/folder_OR_file

在过去某次提交中已删除了文件/文件夹:

  1. 使用git log --diff-filter=D --summary获取已删除文件/文件夹的提交详情;
  2. 使用git checkout $commit~1 path/to/folder_OR_file来还原已删除的文件/文件夹。 其中,$commit是您在第1步找到的提交的SHA值,例如c7578994。

5
在我们的情况下,我们在提交时意外删除了文件,并在几个提交之后意识到了我们的错误,想要恢复所有被删除但未修改的文件。
基于Charles Bailey的优秀答案,这是我的一行代码:
git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)

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