在Git仓库中查找并恢复已删除文件的方法

在Git仓库中查找并恢复已删除文件的方法

技术背景

在使用Git进行版本控制时,有时会不小心删除文件,或者在某些提交中误删了文件。Git提供了多种方法来查找并恢复这些已删除的文件,以确保数据的完整性和项目的正常进行。

实现步骤

1. 查找删除文件的提交

可以使用以下命令找到最后一个影响给定文件路径的提交,由于该文件不在HEAD提交中,那么前一个提交必定是删除它的提交:

1
git rev-list -n 1 HEAD -- <file_path>

2. 恢复文件

方法一:使用^符号

1
git checkout <deleting_commit>^ -- <file_path>

或者使用单行命令:

1
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

如果使用zsh且启用了EXTENDED_GLOB选项,^符号可能无法工作,可以使用~1代替:

1
git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"

方法二:通过git log查看删除文件的提交

1
git log --diff-filter=D --summary

记录所需的提交哈希,例如e4e6d4d5e5c59c69f3bd7be2,然后从该提交的前一个提交(~1)恢复删除的文件:

1
git checkout e4e6d4d5e5c59c69f3bd7be2~1 path/to/file.ext

方法三:恢复文件夹中所有删除的文件

1
git ls-files -d | xargs git checkout --

方法四:恢复最新HEAD提交中存在的已删除文件

1
git checkout HEAD -- path/to/file.ext

方法五:使用git-bisect

1
2
3
4
git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>
git bisect run '[ -e foo.bar ]'

找到删除文件的提交后,可以使用git-revert撤销更改:

1
2
git bisect reset
git revert <the offending commit>

或者回退一个提交并手动检查:

1
2
3
4
git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

方法六:使用别名

可以设置别名来简化恢复操作,例如:

1
git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

使用时:

1
git restore my_deleted_file

方法七:使用GUI工具(如WebStorm)

在WebStorm中,右键单击包含已删除文件的路径,选择Git -> Show History,在历史记录中找到删除文件的提交,双击文件名即可恢复。

方法八:结合coreutils工具

1
2
git log --raw | grep -B 30 $'D\t.*deleted_file.c'
git checkout <rev>^ -- path/to/refound/deleted_file.c

方法九:恢复特定提交中删除的多个文件

1
2
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

方法十:处理悬空提交

1
2
git fsck --lost-found
git reset --hard <commit id>

方法十一:使用git restore命令(Git 2.23及以上)

1
2
git log --diff-filter=D --oneline -- path/to/file | cut -f -d ' '
git restore --source=4711174^ path/to/file

3. 不同场景下的恢复方法

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

  • 如果尚未对更改进行索引(git add),可以恢复目录内容:
1
git restore -- path/to/folder_OR_file
  • 如果删除操作已被索引,应先重置:
1
git reset -- path/to/folder_OR_file

然后执行:

1
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值。

核心代码

以下是一些核心代码示例:

1
2
3
4
5
6
7
8
# 查找删除文件的提交
git rev-list -n 1 HEAD -- <file_path>
# 恢复文件
git checkout <deleting_commit>^ -- <file_path>
# 恢复文件夹中所有删除的文件
git ls-files -d | xargs git checkout --
# 恢复最新HEAD提交中存在的已删除文件
git checkout HEAD -- path/to/file.ext

最佳实践

  • 定期备份重要文件和提交记录,以防止数据丢失。
  • 在进行重要操作前,先创建一个新的分支,以便在出现问题时可以轻松回滚。
  • 使用别名来简化常用的恢复命令,提高工作效率。

常见问题

1. ^符号在zsh中无法工作怎么办?

如果使用zsh且启用了EXTENDED_GLOB选项,^符号可能无法工作,可以使用~1代替。

2. git restore命令是实验性的,是否可以放心使用?

git restore命令在Git 2.23及以上版本中是实验性的,虽然可以使用,但在重要项目中建议先在测试环境中进行验证。

3. 如果文件被删除后又进行了多次提交,是否还能恢复?

可以恢复,只要通过git log等命令找到删除文件的提交,然后从该提交的前一个提交恢复文件即可。


在Git仓库中查找并恢复已删除文件的方法
https://119291.xyz/posts/2025-05-09.find-and-restore-deleted-file-in-git-repository/
作者
ww
发布于
2025年5月9日
许可协议