Journal
博客
…技术笔记与思考碎片,可按分类与标签筛选浏览。
在开发过程中,不小心把 config.yaml(包含Mysql,Redis 等配置)提交进了 Git 仓库。
虽然随后通过提交把文件删除并加入了 .gitignore,但回过头来看,这个处理方式是不完整的。
原因很简单: Git 会永久保留历史提交,只要有人 checkout 到旧 commit,配置内容依然是明文可见的。
很多人第一次遇到这个问题,都会下意识做这些操作:
这些方式的共同问题是: 它们只影响当前分支状态,不会影响 Git 历史中的对象。
只要配置文件曾经被提交过,就必须假设已经泄露。
目前官方推荐的是 git-filter-repo,专门用于:
如果提示找不到命令,把路径加入 PATH:
--mirror 的目的不是开发,而是为了:
执行完成后,git-filter-repo 会:
如果看到类似:
说明处理是成功的。
git-filter-repo 会主动移除 origin,这是为了防止误推送。
这一步会直接用新的干净历史替换远端仓库。
在任意新 clone 的仓库中执行:
如果没有任何输出,说明该文件已经不存在于历史中。
同时提供示例文件:
只放结构,不放真实值。
无论泄露时间长短,都应视为已暴露:
历史清理只能解决 Git 层面的问题,无法撤回已经泄露的密钥。
历史被重写后,所有协作者必须同步仓库状态:
如果有人直接 git pull 并再次推送,旧历史可能会被带回远端。
这次问题的根源不是 Git 操作失误,而是:
对 Git 历史不可变性的低估。
只要敏感信息进入过仓库,正确的处理方式只有一种:
重写历史,而不是覆盖提交。
git filter-repo + mirror + force push是目前最稳妥、最可控的一套方案。