痛点:为什么我们的 .git 文件夹越来越大?
在日常开发中,你是否遇到过这样的情况:项目代码本身没多少,但执行 git clone 时却要下载几个 G 的数据?或者偶尔手抖,把包含密码的配置文件、测试用的 .mp4 视频、甚至是庞大的 .node_modules 目录提交到了 Git 中。
即便你随后立刻执行了 git rm 删除了这些文件,并在最新的 commit 中修复了问题,Git 的核心机制依然会忠实地在历史树中永久保留它们。这些'历史遗留物'会持续占用磁盘空间,拖慢拉取代码的速度。
为了彻底将它们从历史记录中抹除,我们需要重写 Git 历史。
过去,我们常使用 git filter-branch 或 BFG Repo-Cleaner。推荐使用 Git 官方推荐的替代工具:git-filter-repo。它不仅速度极快,而且功能强大、语法简洁。
神器登场:什么是 git-filter-repo?
git-filter-repo 是一个用于重写 Git 历史记录的通用工具。根据 Git 官方文档的建议,由于 git filter-branch 存在性能和安全性问题,git-filter-repo 已经成为了执行此类任务的首选标准。
1. 安装指南
安装过程非常简单。由于它是基于 Python 编写的,最推荐的安装方式是使用 pip:
# 确保你的系统中已安装 Python 3
pip install git-filter-repo
如果你是 macOS 用户,也可以直接使用 Homebrew:
brew install git-filter-repo
实战演练:常见场景清理指南
⚠️ 终极警告: 重写历史会改变所有受影响 commit 的 Hash 值。在进行以下任何操作前,请务必备份你的项目,或者在一个全新的 clone 目录中进行测试!
场景一:批量删除特定后缀的媒体文件(如 .png 和 .mp4)
这也是我在实际开发中最常遇到的情况。假设我们需要把项目中所有历史提交里的图片和视频彻底清理掉,只需在项目根目录执行:
git filter-repo --path-glob '*.png' --path-glob '*.mp4' --invert-paths --force
参数解析:
--path-glob: 用于指定匹配模式。--invert-paths: 这是一个非常巧妙的参数,它告诉工具:保留除了匹配路径之外的所有文件。换句话说,就是删除匹配到的文件。--force: 如果你不是在一个 fresh clone(全新克隆)的裸仓库(bare repo)中操作,工具会出于安全考虑阻止你,加上此参数可强制执行。
场景二:删除特定的敏感目录或文件
如果有人不小心把 config/database.yml(包含线上数据库密码)提交了,你可以这样抹除它:
git filter-repo --path config/database.yml --invert-paths --force
删除整个文件夹(比如不小心提交的 dist 编译产物):
git filter-repo --path dist/ --invert-paths --force


