以下是使用 git filter-repo 清除仓库敏感文件并同步至远端的完整操作文档。请严格按照顺序执行,避免历史污染或数据丢失。
📋 前置准备
-
通知团队暂停开发:在操作期间禁止任何人推送代码,否则其提交会重新引入被删除的文件。
-
完整备份仓库 :
bash# 克隆一份完整镜像作为灾备 git clone --mirror <repo-url> backup-repo.git -
安装 git-filter-repo (推荐使用 pip):
bashpip install git-filter-repo -
确保本地仓库是最新全量克隆 (非 shallow clone):
bashgit fetch --all git pull --all
🔧 第一步:执行历史重写
⚠️
filter-repo默认重写所有分支和标签,与当前所在分支无关。无需切换分支。
bash
# 从整个仓库历史中彻底移除 .env 文件
git filter-repo --path .env --invert-paths --force
--path .env:指定目标文件路径(支持通配符,如*.env、config/.env)--invert-paths:排除该路径(即删除),不加此参数则为仅保留--force:跳过 "fresh clone" 安全检查(确认已备份后可加)
✅ 第二步:验证清除结果
必须在推送前确认,否则可能将未清理的历史推送到远端。
bash
# 搜索所有分支/标签历史中是否仍存在 .env
git log --all --full-history -- .env
- 无任何输出 → ✅ 清除成功,继续下一步
- 有输出 → ❌ 仍有残留,停止操作,检查路径是否正确或是否存在同名变体(如
.env.local)
🚀 第三步:推送到远端
3.1 解除 GitLab/GitHub 分支保护
若 master/main/dev 等分支受保护,需先在平台设置中:
- 开启 Allowed to force push,或
- 临时 Unprotect 分支(推送后立即恢复)
3.2 更新远程跟踪引用(防止 stale info)
bash
git fetch origin
3.3 强制推送所有分支和标签
bash
git push origin --all --force-with-lease
git push origin --tags --force-with-lease
💡 若遇大仓库 HTTPS 推送断开,先执行:
bashgit config http.postBuffer 524288000或改用 SSH 协议推送。推送完成后可恢复默认:
git config --unset http.postBuffer
3.4 恢复分支保护
推送成功后立即回到平台重新启用分支保护规则。
📢 第四步:通知团队成员更新本地仓库
将以下通知发送给所有协作者:
【重要】仓库历史已重写,请按以下步骤更新本地环境
由于安全原因,仓库中的
.env文件已从全部历史中移除。你的本地分支已与远端不兼容,请勿使用git pull(会导致旧历史合并回来)。请对每个本地分支执行:
bashgit fetch origin git reset --hard origin/<branch-name>如果你有未推送的本地提交,请先备份为补丁再重做:
bashgit format-patch origin/<branch-name> --stdout > my-changes.patch git reset --hard origin/<branch-name> git apply my-changes.patch完成后请删除本地的
.env文件(如仍存在于工作区)。
⚠️ 关键注意事项
| 风险点 | 说明 |
|---|---|
| 不可逆操作 | filter-repo 重写后原始 commit hash 永久改变,仅靠备份恢复 |
| CI/CD 缓存 | 检查流水线、构建缓存、Docker 镜像中是否仍包含旧的 .env,需手动清理 |
| 环境变量迁移 | 确保 .env 内容已迁移至安全的密钥管理服务(如 Vault、GitLab CI Variables)后再执行清除 |
| fork / mirror | 如有下游 fork 或镜像仓库,需同步通知其维护者重新同步 |
| GitHub 专用 | GitHub 不会自动 GC 已删除的对象,如需立即生效需联系 GitHub Support 触发 GC |