如果密码、密钥或其他敏感内容进入了 Git 仓库,仅删除当前文件并不能清除历史中的副本。清理历史还会改变提交标识,需要与所有使用仓库的人协调。
从仓库移除敏感数据的基本思路
误提交敏感数据后,可以用 git-filter-repo 等工具重写历史,移除指定文件或替换指定内容。重写操作会产生下文所列副作用,因此要先评估影响。
首先撤销或轮换泄露的凭据。 对密码、令牌和密钥而言,轮换通常能先消除访问风险;有些情况下,这一步已经足够,无须承担重写历史带来的额外影响。
重写历史的副作用
- 再次污染仓库。 同事仍持有旧克隆时,执行
git pull再git push可能把已经移除的敏感提交重新推回去。清理所有克隆也可能复杂而容易出错。 - 丢失他人的工作。 重写和强制推送期间,如果有人仍基于旧历史工作,可能需要重新整理工作,甚至丢失改动。
- 提交哈希改变。 不只含有敏感数据的提交会变化,其后的提交也会得到新的哈希;引用旧提交的工具或自动化可能失效。
- 分支保护受影响。 受保护分支可能禁止强制推送,清理时可能需要暂时关闭相应保护。
- 已关闭的拉取请求出现断裂。 GitHub 显示拉取请求差异所用的内部提交引用可能被清除,导致差异不再可见。这可能影响敏感提交之后的其他拉取请求。
- 正在进行的拉取请求受影响。 提交 SHA 改变可能使差异视图和逐行评论失效。最好先合并或关闭开放的拉取请求,再清理历史。
- 提交和标签签名丢失。 签名依赖提交哈希,因此重写后失效;许多重写工具,包括
git-filter-repo,会移除签名,甚至影响敏感内容进入仓库之前的提交和标签。使用--refs限定处理范围时,务必覆盖历史中包含敏感数据的所有引用,并确保所选范围包含引入敏感数据的提交。 - 敏感内容反而更容易被定位。 持有旧克隆、熟悉 Git 的人,可能从新旧历史开始分叉的位置找到原来的敏感数据。
敏感数据暴露的范围
完整清理通常包含四步:先重写本地仓库历史,再更新 GitHub 上的仓库,然后协调清理其他人的克隆,最后采取措施防止再次误提交。以下分别展开这些步骤及其限制。
使用 git-filter-repo 并强制推送后,可以从 GitHub 上的分支和标签移除相关历史;但敏感提交仍可能存在于以下位置:
- 其他人的克隆;
- 仓库的分叉;
- GitHub 上通过提交 SHA-1 访问的缓存页面;
- GitHub 上引用这些提交的拉取请求。
你不能替其他用户清理他们的克隆。需要联系相关人员,请他们删除并重新克隆,或按照 git-filter-repo 的克隆清理说明处理旧副本。
可以通过 GitHub Support请求清除缓存视图以及引用敏感数据的拉取请求。GitHub Support 不会据此移除非敏感数据,而且只有轮换凭据无法减轻风险时,才会协助清理敏感数据。
如果分叉仍引用敏感提交,这些提交仍然可访问。你需要与分叉所有者协调移除或删除分叉;GitHub 无法为你提供所有分叉所有者的联系方式。行动前应充分评估这些限制。
用 git-filter-repo 从本地历史清除文件
按照以下顺序处理。下面保留官方命令和样例输出。
- 安装
git-filter-repo的最新版本。--sensitive-data-removal需要 2.47 或更新版本。例如,使用 Homebrew:
brew install git-filter-repo
其他安装方式见 INSTALL.md。
- 克隆仓库,用实际用户名和仓库名替换占位内容:
git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
- 进入仓库工作目录:
cd YOUR-REPOSITORY
- 要从所有相关历史中移除一个文件,执行:
git-filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
路径相对于仓库根目录。如果文件曾改名或移到其他目录,必须一并处理它的旧路径:可以增加多个 --path 参数,也可以为其他路径再次调用命令。
如果要替换所有非二进制文件历史中的指定文本,而不是删除整个文件,把要替换的内容放进仓库外的 passwords.txt 文件,然后执行:
git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt
-
再次检查历史,确认需要清除的文件或内容已经彻底移除。
-
检查受到影响的拉取请求数量,因为后续操作可能使这些拉取请求的差异无法显示。以下为官方样例输出:
$ grep -c '^refs/pull/.*/head$' .git/filter-repo/changed-refs
4
如需查看具体拉取请求,可运行:
$ grep '^refs/pull/.*/head$' .git/filter-repo/changed-refs
refs/pull/589/head
refs/pull/602/head
refs/pull/604/head
refs/pull/605/head
拉取请求编号位于第二个和第三个斜杠之间,示例中是 589、602、604 和 605。如果受到影响的数量超出预期,可以丢弃这个克隆,重新安排重写,或放弃该清理方案。进入下一步后,拉取请求受到的损坏将无法撤销。
- 确认无误后,强制推送所有引用:
git push --force --mirror origin
--mirror 已经包含强制更新的含义,这里显式保留 --force 是为了提醒:清理期间别人推送的改动可能被覆盖。
refs/pull/ 下的引用是只读的,对它们的推送失败属于预期情况。如果其他引用也失败,可能需要暂时调整分支保护,再重试,直到只有 refs/pull/ 引用失败。
从 GitHub 完成清理
本地重写与推送之后,还要清理 GitHub 端和其他人的副本。
-
向 GitHub Support提交工单,提供:仓库所有者和仓库名、受影响的拉取请求数量,以及
git-filter-repo在以NOTE:开头的输出中列出的 First Changed Commit(s)。如果敏感信息处理产生了孤立的 Git LFS 对象,工具还会报告这一点,并指出包含孤立对象列表的文件名;将该文件上传到工单。如果除拉取请求之外的全部引用已经清理,且没有分叉引用敏感提交,GitHub Support 可以取消引用或删除受影响的拉取请求、执行垃圾回收、清除缓存视图,并移除孤立的 LFS 对象。再次强调:这种协助仅针对无法通过轮换凭据减轻风险的敏感数据,不用于移除非敏感内容。
-
告知同事:基于旧历史创建的分支应当 rebase,不要 merge。只要一次合并把包含敏感数据的旧历史重新引入,清理就可能被抵消。具体操作参见 Pro Git 的变基说明和
git-filter-repo的克隆清理说明。
防止再次误提交
以下做法可以降低敏感数据再次进入仓库的概率;更多建议见 GitHub 的防止数据泄露指南。
- 将包含敏感数据的文件加入
.gitignore,并提交、推送这一忽略规则。 - 不要在源码中硬编码秘密;使用环境变量或专用密钥管理工具,例如 AWS Secrets Manager、HashiCorp Vault。
- 使用 pre-commit hook 检查秘密,例如
git-secrets或gitleaks。每位协作者都要配置这类检查。 - 使用 GitHub Desktop 或 gitk等可视化工具,检查将要提交的改动。
- 避免
git add .和git commit -a;优先用git add filename、git rm filename明确选择文件。 - 使用
git add --interactive逐项查看并暂存改动。 - 提交前运行
git diff --cached检查已暂存内容。它展示的是不带-a的git commit将要提交的改动。 - 启用仓库的推送保护。
延伸阅读
git-filter-repo手册,特别是敏感数据清理部分。- Pro Git:重写历史。
- GitHub 秘密扫描。
来源与许可
来源:GitHub Docs — Removing sensitive data from a repository,作者 GitHub 文档贡献者;2026-10-03核对英文原文并整理中文表述,保留全部示例命令和输出。文档内容按 CC BY 4.0提供,本文作中文翻译。许可依据:github/docs README。
示例代码按 MIT 许可提供。Copyright (c) 2026 GitHub, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.











暂无评论内容