如何在整个 Git 历史中搜索代码内容(grep)
全历史搜索代码:git grep "模式" $(git rev-list --all) 搜索所有提交的文件内容;git log -S"字符串" 找该字符串出现/消失的提交;git log -G 支持正则。这是代码考古的标配组合。
两个主力工具:git grep "模式" $(git rev-list --all) 在所有提交的所有文件里做内容搜索;git log -S"字符串"(pickaxe)找该字符串被引入或移除的提交——回答"这段代码什么时候出现/消失的"最准。
git grep 搜索全历史
git grep "api_key" $(git rev-list --all)
# 输出:<提交哈希>:<文件路径>:<匹配行>
限定范围更快:
git grep "password" $(git rev-list main) -- '*.js' # 只看 main 分支的 js 文件
git grep "TODO" v1.0.0 # 搜某个 tag 的快照
git log -S/-G 找变更点
git log -S"encryptPassword" --oneline # 该字符串出现或消失的提交
git log -G"db\.(connect|query)" --oneline # 正则匹配 diff 内容的提交
git log -S"密钥" -p # 连 diff 一起看
-S 适合找确切的字符串增删;-G 匹配每次提交的 diff 行,正则能力强但更慢。
典型场景
- 密钥泄露排查:
git grep "AKIA" $(git rev-list --all)找 AWS key 是否进过仓库; - 找"谁删了那个函数":
git log -S"函数名" --oneline,最后一个含变动的提交就是; - 某配置项的历史取值:
git log -p -- config.yml | grep 关键词。
常见问题(FAQ)
Q:搜索很慢怎么办?
大仓库全历史 grep 很重。缩小范围:限定分支、路径(-- '*.py')、时间(--since),或用 git rev-list --since=... 生成更短的提交列表。
Q:搜到的内容想直接看文件?
git show <哈希>:<路径> 输出该提交时该文件的完整内容。
Q:GitHub 网页能搜历史吗?
GitHub 的代码搜索默认只搜默认分支当前版本。历史搜索还是本地 clone 后用上面的命令。