跳至主要内容

从仓库中删除敏感数据

如果您将敏感数据(例如密码或 SSH 密钥)提交到 Git 仓库,您可以从历史记录中将其删除。

关于从仓库中删除敏感数据

当使用 git filter-repo 或 BFG Repo-Cleaner 等工具更改仓库历史记录时,务必了解其影响,尤其是关于开放的拉取请求和敏感数据。

git filter-repo 工具和 BFG Repo-Cleaner 会重写仓库的历史记录,这会更改您更改的现有提交的 SHA 值以及任何依赖的提交。更改的提交 SHA 值可能会影响仓库中的开放拉取请求。我们建议在从仓库中删除文件之前合并或关闭所有开放的拉取请求。

您可以使用 git rm 从最新提交中删除文件。有关删除使用最新提交添加的文件的信息,请参阅 "关于 GitHub 上的大文件."

关于敏感数据泄露

本文档介绍了如何使包含敏感数据的提交在 GitHub.com 上的仓库中无法从任何分支或标签访问。但是,这些提交可能仍然可以通过其他方式访问。

  • 在仓库的任何克隆或分支中
  • 通过 GitHub 上缓存视图中的 SHA-1 哈希值直接访问
  • 通过引用它们的任何拉取请求。

您无法从其他用户对您仓库的克隆中移除敏感数据,但您可以通过联系 GitHub 支持门户 来永久移除 GitHub 上拉取请求中缓存的视图和对敏感数据的引用。

重要

GitHub 支持不会移除非敏感数据,并且只会在我们确定风险无法通过轮换受影响的凭据来缓解的情况下,协助移除敏感数据。

一旦您将提交推送到 GitHub,您应该认为提交中的任何敏感数据都已泄露。如果您提交了密码,您应该更改它。如果您提交了密钥,请生成一个新的密钥。

如果引入敏感数据的提交存在于任何分支中,它将继续在那里可访问。您需要与分支所有者协调,要求他们移除敏感数据或完全删除分支。GitHub 无法提供这些所有者的联系信息。

在您决定重写仓库历史记录时,请考虑这些限制和挑战。

从仓库历史记录中清除文件

您可以使用 git filter-repo 工具或 BFG Repo-Cleaner 开源工具从仓库历史记录中清除文件。

注意

如果敏感数据位于被识别为二进制文件的文件中,您需要从历史记录中移除该文件,因为您无法修改它来移除或替换数据。

使用 BFG

BFG Repo-Cleaner 是一个由开源社区构建和维护的工具。它提供了一个比 git filter-repo 更快、更简单的替代方案来移除不需要的数据。

例如,要移除包含敏感数据的文件并保留最新的提交,请运行

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

要替换仓库历史记录中所有可以找到的 passwords.txt 中列出的所有文本,请运行

bfg --replace-text passwords.txt

移除敏感数据后,您必须强制推送更改到 GitHub。强制推送会重写仓库历史记录,这会从提交历史记录中移除敏感数据。如果您强制推送,它可能会覆盖其他人基于其工作而创建的提交。

git push --force

请参阅 BFG Repo-Cleaner 的文档以获取完整的使用说明和下载说明。

使用 git filter-repo

警告

如果您在隐藏更改后运行 git filter-repo,您将无法使用其他隐藏命令检索您的更改。在运行 git filter-repo 之前,我们建议您取消隐藏所做的任何更改。要取消隐藏您隐藏的最后一组更改,请运行 git stash show -p | git apply -R。有关更多信息,请参阅 Git 工具 - 隐藏和清理

为了说明 git filter-repo 的工作原理,我们将向您展示如何从存储库的历史记录中删除包含敏感数据的文件,并将其添加到 .gitignore 中以确保不会意外重新提交。

  1. 安装最新版本的 git filter-repo 工具。您可以手动安装 git-filter-repo 或使用包管理器。例如,要使用 HomeBrew 安装该工具,请使用 brew install 命令。

    brew install git-filter-repo
    

    有关更多信息,请参阅 newren/git-filter-repo 存储库中的 INSTALL.md

  2. 如果您还没有在本地计算机上拥有包含敏感数据的存储库的本地副本,请 克隆存储库

    $ git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
    > Initialized empty Git repository in /Users/YOUR-FILE-PATH/YOUR-REPOSITORY/.git/
    > remote: Counting objects: 1301, done.
    > remote: Compressing objects: 100% (769/769), done.
    > remote: Total 1301 (delta 724), reused 910 (delta 522)
    > Receiving objects: 100% (1301/1301), 164.39 KiB, done.
    > Resolving deltas: 100% (724/724), done.
    
  3. 导航到存储库的工作目录。

    cd YOUR-REPOSITORY
    
  4. 运行以下命令,将 PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA 替换为 **要删除的文件的路径,而不仅仅是文件名**。这些参数将

    • 强制 Git 处理(但不会检出)每个分支和标签的整个历史记录

    • 删除指定的文件,以及由此产生的任何空提交

    • 删除存储在 .git/config 文件中的某些配置,例如远程 URL。您可能需要事先备份此文件,以便以后恢复。

    • 覆盖您现有的标签

        $ git filter-repo --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
        Parsed 197 commits
        New history written in 0.11 seconds; now repacking/cleaning...
        Repacking your repo and cleaning out old unneeded objects
        Enumerating objects: 210, done.
        Counting objects: 100% (210/210), done.
        Delta compression using up to 12 threads
        Compressing objects: 100% (127/127), done.
        Writing objects: 100% (210/210), done.
        Building bitmaps: 100% (48/48), done.
        Total 210 (delta 98), reused 144 (delta 75), pack-reused 0
        Completely finished after 0.64 seconds.
      

      重要

      如果包含敏感数据的文件曾经存在于任何其他路径(因为它被移动或重命名),则您也必须在这些路径上运行此命令。

  5. 将包含敏感数据的文件添加到 .gitignore 中,以确保您不会意外地再次提交它。

    $ echo "YOUR-FILE-WITH-SENSITIVE-DATA" >> .gitignore
    $ git add .gitignore
    $ git commit -m "Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore"
    > [main 051452f] Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore
    >  1 files changed, 1 insertions(+), 0 deletions(-)
    
  6. 仔细检查您是否已从存储库的历史记录中删除了所有想要删除的内容,以及所有分支是否都已检出。

  7. git filter-repo 工具将自动删除您配置的远程服务器。使用 git remote set-url 命令恢复您的远程服务器,将 OWNERREPO 替换为您的存储库详细信息。有关更多信息,请参阅 "管理远程存储库。"

    git remote add origin https://github.com/OWNER/REPOSITORY.git
    
  8. 一旦您对存储库的状态感到满意,并且您已设置了适当的远程存储库,请强制推送您的本地更改以覆盖 GitHub.com 上的存储库,以及您已推送的所有分支。强制推送是删除敏感数据提交历史记录所必需的。

    $ git push origin --force --all
    > Counting objects: 1074, done.
    > Delta compression using 2 threads.
    > Compressing objects: 100% (677/677), done.
    > Writing objects: 100% (1058/1058), 148.85 KiB, done.
    > Total 1058 (delta 590), reused 602 (delta 378)
    > To https://github.com/YOUR-USERNAME/YOUR-REPOSITORY.git
    >  + 48dc599...051452f main -> main (forced update)
    
  9. 为了从 您的标记版本 中删除敏感文件,您还需要强制推送您的 Git 标签。

    $ git push origin --force --tags
    > Counting objects: 321, done.
    > Delta compression using up to 8 threads.
    > Compressing objects: 100% (166/166), done.
    > Writing objects: 100% (321/321), 331.74 KiB | 0 bytes/s, done.
    > Total 321 (delta 124), reused 269 (delta 108)
    > To https://github.com/YOUR-USERNAME/YOUR-REPOSITORY.git
    >  + 48dc599...051452f main -> main (forced update)
    

完全从 GitHub 中删除数据

在使用 BFG 工具或 git filter-repo 删除敏感数据并将更改推送到 GitHub 后,您必须采取几个步骤才能完全从 GitHub 中删除数据。

  1. 通过 GitHub 支持门户 联系我们,并要求删除 GitHub 上拉请求中对敏感数据的缓存视图和引用。请提供存储库名称和/或您需要删除的提交链接。

    重要

    GitHub 支持不会移除非敏感数据,并且只会在我们确定风险无法通过轮换受影响的凭据来缓解的情况下,协助移除敏感数据。

  2. 告诉您的合作者 变基,而不是合并他们从您的旧(受污染的)存储库历史记录中创建的任何分支。一次合并提交可能会重新引入您刚刚费力清除的一些或全部受污染的历史记录。

  3. 一段时间后,如果您确信 BFG 工具/git filter-repo 没有产生任何意外的副作用,您可以使用以下命令强制本地存储库中的所有对象被取消引用并垃圾回收(使用 Git 1.8.5 或更高版本)。

    $ git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
    $ git reflog expire --expire=now --all
    $ git gc --prune=now
    > Counting objects: 2437, done.
    > Delta compression using up to 4 threads.
    > Compressing objects: 100% (1378/1378), done.
    > Writing objects: 100% (2437/2437), done.
    > Total 2437 (delta 1461), reused 1802 (delta 1048)
    

    注意

    您也可以通过将过滤后的历史记录推送到新的或空的存储库,然后从 GitHub 创建一个新的克隆来实现这一点。

避免将来意外提交

防止贡献者进行意外提交可以帮助您防止敏感信息泄露。有关更多信息,请参阅“防止组织中数据泄露的最佳实践”。

有一些简单的技巧可以避免提交您不想提交的内容。

  • 使用 GitHub Desktopgitk 等可视化程序来提交更改。可视化程序通常使您更容易查看每次提交将添加、删除和修改哪些文件。
  • 避免在命令行中使用通配符命令 git add .git commit -a - 使用 git add filenamegit rm filename 来单独暂存文件,而不是。
  • 使用 git add --interactive 来单独查看和暂存每个文件中的更改。
  • 使用 git diff --cached 来查看您已暂存以提交的更改。只要您不使用 -a 标志,这就是 git commit 将产生的确切差异。
  • 为您的存储库启用推送保护,以检测和防止包含硬编码秘密的推送被提交到您的代码库。有关更多信息,请参阅“存储库和组织的推送保护”。

进一步阅读