filter-branch 是什么
git filter-branch 是旧式历史重写工具:能对每个提交执行过滤(改文件、删路径、改作者信息),但用法复杂、速度慢,官方文档明确建议改用 git filter-repo 等专用工具。存量脚本与老文档里仍会见到它;维护旧流程的关键是认清行为差异,并保证重写后的收尾——reflog 过期、远端强推、协作者重新克隆——整套到位。
基本信息
| 状态 | 仍可用但不推荐新项目使用,官方文档提示改用专用工具 |
|---|---|
| 常用参数 | --tree-filter 逐提交检出工作树;--index-filter 只改索引 |
| 示例 | git filter-branch --tree-filter <命令> HEAD |
| 替代 | git filter-repo(删除、替换、拆分等场景更全更快) |
| 备份引用 | 重写前写入 refs/original/,重复执行需 --force |
| 收尾 | reflog 过期、gc 回收、远端强推、协作者重新克隆 |
典型使用场景
- 大文件清理:从历史中删除误提交的大文件
- 敏感内容清除:密钥误提交后重写历史(配合凭证轮换)
- 作者信息修正:批量修改邮箱域名或姓名映射
- 目录剥离:把子目录历史拆出为独立仓库
- 兼容旧文档:团队脚本仍引用 filter-branch 时理解其行为
- 迁移演练:在克隆副本上验证 filter-repo 的等效重写结果
迁移对照
迁移对照
# 旧写法(示例思路):从全部历史删除某路径
# git filter-branch --index-filter 'git rm --cached --ignore-unmatch secret.txt' --prune-empty HEAD
# 新工具等效写法(推荐)
git filter-repo --path secret.txt --invert-paths
# 重写后收尾(两种工具通用)
# git reflog expire --expire=now --all && git gc --prune=nowfilter 参数对照
| 参数 | 作用 | 代价 |
|---|---|---|
| --tree-filter | 每提交检出工作树执行命令 | 最慢,磁盘消耗大 |
| --index-filter | 只改写索引不检出 | 快得多,命令需用索引操作 |
| --prune-empty | 删除变空的提交 | 历史更干净 |
| --force | 覆盖已有重写引用 | 重跑前先清理临时引用 |
新项目直接使用 filter-repo;老项目迁移前先在克隆上验证重写结果与文件差异。
filter-branch 会把原引用备份到 refs/original/ 并拒绝重复执行:确认无误后按收尾流程清理,别留着占对象。
重写是「换号」操作:所有下游克隆都要重新同步,公告模板与冻结窗口提前准备。