Git_查看已删除文件的历史
文件不见了,没法去选中文件查看历史记录(一般支持 git 的 IDE 或者应用),第一反应是翻 commit 记录,翻了半天没找到,即使翻到了也很费功夫——其实 git log 就可以解决。
git log 本质是三件事的组合:在哪个范围内找、按什么条件过滤、用什么格式输出。把这三块拼对了,几条命令就能定位。
命令结构
git log <branch | --all> [过滤参数] [输出参数] -- <path>
输出较多时,git log 默认用 less 分页显示。j / k 上下滚动(一般终端都支持鼠标滚动),q 退出。
参数说明
范围控制
| 参数 | 说明 |
|---|---|
--all | 遍历所有分支和 tag,兜底用 |
<branch> | 只看指定分支,比 --all 干净 |
A..B | 只看 B 有、A 没有的提交,适合查当前分支的新增改动 |
过滤参数
--diff-filter=<字母> :按文件操作类型筛选
| 值 | 含义 |
|---|---|
A | 新增 |
M | 修改 |
D | 删除 |
R | 重命名 |
查删除用 --diff-filter=D,查重命名用 R,两者都不排除的话文件可能只是被移走了。也可以组合使用,如 --diff-filter=AD。
--follow:追踪文件重命名 / 移目录前的历史。默认的 git log -- path 只看这个路径的提交,文件改名后旧路径的历史就断了;加上 --follow 会沿路径链往前查。注意 --follow 依赖内容相似度来识别 rename,如果文件改动很大同时移了路径,可能识别不到。
-S "text" :查某段文本"出现或消失"的提交。不知道文件路径,只记得某段代码时用这个。
-G "regex" :按正则匹配 diff 内容,比 -S 更宽松。
举个例子,如果某次提交把
baseUrl = "http://a.com"改成了baseUrl = "http://b.com",-S "baseUrl"不会命中(因为该字符串总数没变),但-G "baseUrl"会命中(因为 diff 里有包含baseUrl的改动行)。
输出参数
| 参数 | 说明 |
|---|---|
--name-status | 显示文件名 + 操作状态(A/M/D/R),最常用 |
--name-only | 只列文件名,不带状态 |
--summary | 显示 delete mode / create mode,直观看结构变化 |
--full-history | 不省略 merge 路径,文件被合并覆盖时普通 log 可能查不到 |
路径限定
-- <path>
-- 后面跟路径,区分参数和文件名,建议始终写上,否则文件名与参数重名时会解析出错,通配符也可能被 shell 提前展开。
** 匹配任意层级目录,记不清文件具体在哪个子目录时很有用:
# 只记得文件在 cdn 目录下某处,不知道完整路径
git log --name-status -- "**/cdn/**/axios.min.js"
这条命令会匹配所有含 cdn 的路径,比如 src/cdn/v3/axios.min.js 或 assets/cdn/axios.min.js 都能命中。
关于"文件历史"的一个认知点
git log -- <path> 是按路径过滤提交历史,而不是在追踪某个文件实例。Git 没有"文件唯一 ID",它只记录 blob(内容)和 path(路径)。
因此,同名文件被删除后重新创建,历史里会看到一个 D 和一个 A,它们属于同一路径的两次变化,不代表是同一个文件。多个目录下有同名文件时(如 app-a/axios.min.js 和 app-b/axios.min.js),通配查询会把所有路径的变更都列出来,注意区分。
关于 R100(重命名):Git 并不记录"重命名操作"本身,而是在 diff 时根据内容相似度推断——本质仍是 D + A,但相似度足够高(默认 > 50%)时就显示为 R,R100 表示内容 100% 相同。将文件从一个目录移到另一个目录时,也会显示为重命名记录:
R100 assets/app-b/axios.min.js assets/app-a/axios.min.js
常用命令
# 查当前分支是否删过指定文件(文件名模糊匹配)
git log --diff-filter=D --summary -- '*axios.min.js'
# 精确查某个分支的删除记录
git log main --diff-filter=D --summary -- '*axios.min.js'
# 全局查,所有分支上指定文件的删除记录
git log --all --diff-filter=D --summary -- '*axios.min.js'
# 查所有变更类型,判断是删除还是重命名
git log --all --name-status -- '*axios.min.js'
# 文件曾经改名/移目录,追踪改名前的历史
git log --follow -- src/lib/axios.min.js
# 只知道代码片段,不知道文件在哪
git log -S "axios" -p --all
# 记得目录名但不知道完整路径,用 ** 匹配任意层级
git log --name-status -- "**/cdn/**/axios.min.js"
# 找到 commit 后看具体改了什么
git show <commit-id>
排查套路
文件消失了,按这个顺序查:
Step 1:先确认文件有没有出现过
git log --all --name-status -- '*axios.min.js'
Step 2:看输出里的状态标记
D src/cdn/axios.min.js # 被删了
R100 src/cdn/axios.min.js src/lib/axios.min.js # 被移走了
如果啥都没有,文件可能从来不叫这个名字,改用 -S 搜代码片段。
Step 3:找到 commit,看具体内容
git show <commit-id>
几个容易踩的坑
文件"消失"不一定是被删了,常见情况有三种:被 D 标记删除、被 R 重命名/移目录、被 merge 覆盖(普通 log 看不到,要加 --full-history)。
不要一条条翻 commit。--name-status + --diff-filter + -S 才是正确姿势。
知道文件名就用路径查,不知道路径就用 *filename 通配,连文件都不确定就用 -S 搜代码片段。文件曾经改名的,记得加 --follow。