如何在项目提交历史中查找已删除的文件
技术背景
在项目开发过程中,有时会不小心删除文件,或者由于历史清理等原因文件被删除。为了恢复这些文件,需要从项目的提交历史中查找它们。Git作为一个强大的版本控制系统,提供了多种方法来实现这一目的。
实现步骤
1. 不知道文件确切路径
如果不知道文件的确切路径,可以使用以下命令查找涉及该文件的所有提交:
1
| git log --all --full-history -- "**/thefile.*"
|
2. 知道文件路径
若知道文件的路径,可以使用以下命令查看所有分支中涉及该文件的提交:
1
| git log --all --full-history -- <path-to-file>
|
3. 显示指定版本的文件
找到想要的文件版本后,使用以下命令显示该版本的文件内容:
1
| git show <SHA> -- <path-to-file>
|
4. 恢复文件到工作副本
使用以下命令将文件恢复到工作副本:
1
| git checkout <SHA>^ -- <path-to-file>
|
注意,这里的^
符号表示获取指定提交之前的版本,因为在<SHA>
提交时文件已被删除,所以需要查看前一个提交来获取已删除文件的内容。
5. 获取已删除文件列表
使用以下命令获取已删除文件的列表,并复制已删除文件的完整路径:
1
| git log --diff-filter=D --summary | grep delete
|
6. 查找提交ID
使用以下命令查找涉及该文件的提交ID:
1
| git log --all -- FILEPATH
|
7. 显示已删除文件的差异
使用以下命令显示已删除文件的差异:
1
| git show COMMIT_ID -- FILE_PATH
|
可选地,可以使用>
将输出写入文件:
1
| git show COMMIT_ID -- FILE_PATH > deleted.diff
|
8. 不确定文件路径或扩展名
如果不确定文件的路径或扩展名,可以按以下步骤操作:
步骤0:进入Git项目根目录
步骤1:查找完整路径
1
| git log --diff-filter=D --summary | grep delete | grep MyFile
|
步骤2:确定影响该文件的所有提交
1
| git log --oneline --follow -- full/path/to/MyFile.js
|
步骤3:检出文件
如果选择列出的第一个提交(按时间顺序最后一个),由于文件在该提交中已被删除,将找不到该文件。需要选择前一个提交:
1
| git checkout bd8374c^ -- full/path/to/MyFile.js
|
9. 查看所有已删除文件的大小和SHA
1
| git log --all --stat --diff-filter=D --oneline
|
添加-p|--patch
参数可以查看文件内容:
1
| git log --all --stat --diff-filter=D -p
|
10. 缩小搜索范围
可以使用路径规范或grep
命令缩小搜索范围:
使用grep
1
| git log --all --stat --diff-filter=D --oneline | grep foo
|
使用路径规范
1
| git log --all --stat --diff-filter=D --oneline -- '*foo*'
|
如果想查看文件内容,可以将路径规范与-p|--patch
参数一起使用:
1
| git log --all --stat --diff-filter=D --oneline --patch -- '*foo*'
|
11. 知道文件位置
如果知道文件的位置,可以使用以下命令:
1
| git log --all --full-history -- someFileName
|
12. 总结步骤
步骤1:在已删除文件的历史记录中搜索文件的完整路径
1
| git log --diff-filter=D --summary | grep filename
|
步骤2:从文件被删除之前的提交中恢复文件
1 2 3 4 5 6 7 8
| restore () { filepath="$@" last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}') echo "Restoring file from commit before $last_commit" git checkout $last_commit^ -- $filepath }
restore my/file_path
|
13. 使用git-filter-repo
如果甚至不知道文件的名称,可以使用git-filter-repo
快速识别仓库中所有已删除的文件,并显示它们的大小和删除日期:
1
| git filter-repo --analyze
|
结果会输出到.git\filter-repo\analysis\path-deleted-sizes.txt
文件中。找到想要的文件后,可以使用以下命令查找涉及该文件的提交:
1
| git log --all --full-history -- <filename>
|
核心代码
恢复文件函数
1 2 3 4 5 6
| restore () { filepath="$@" last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}') echo "Restoring file from commit before $last_commit" git checkout $last_commit^ -- $filepath }
|
最佳实践
- 在进行文件恢复操作之前,建议先备份当前的工作副本,以防意外覆盖。
- 使用
gitk
等可视化工具可以更方便地浏览提交历史,找到想要的文件版本。
常见问题
1. git checkout
时提示文件未找到
如果在执行git checkout <SHA> -- <path-to-file>
时提示文件未找到,可能是因为该提交中文件已被删除。可以尝试使用git checkout <SHA>^ -- <path-to-file>
来获取前一个提交中的文件内容。
2. git-filter-repo
在Windows上安装问题
在Windows上安装git-filter-repo
可能会遇到一些问题,可以参考这里的安装说明。