从Git历史记录中删除敏感文件及其提交记录

509

我想将一个Git项目放到GitHub上,但它包含某些包含敏感数据的文件(用户名和密码,例如capistrano的/config/deploy.rb)。

我知道可以将这些文件名添加到.gitignore中,但这并不会从Git中删除它们的历史记录。

我也不想通过删除/.git目录来重新开始。

有没有一种方法可以删除您Git历史记录中特定文件的所有痕迹?


1
相关内容 https://help.github.com/articles/removing-sensitive-data-from-a-repository/ - Trevor Boyd Smith
12个回答

2
考虑到OP在使用GitHub,如果将敏感数据提交到Git仓库中,可以通过以下选项之一(在下面阅读更多)完全从历史记录中删除它:
  1. 使用git filter-repo工具(在GitHub上查看源代码)。

  2. 使用BFG Repo-Cleaner工具(它是开源的 - 在GitHub上查看源代码)。

在完成上述操作之后,还需要遵循其他步骤。请检查下面的附加部分。
如果目标是删除在最近未推送的提交中添加的文件,请阅读下面的替代方法部分。
为了未来的考虑,以防类似情况再次发生,请查看下面的未来参考部分。
选项1
使用 git filter-repo。在继续之前,请注意:
如果您在隐藏更改后运行 git filter-repo,则无法使用其他隐藏命令检索您的更改。在运行 git filter-repo 之前,我们建议取消隐藏您所做的任何更改。要取消隐藏您最后一组隐藏的更改,请运行 git stash show -p | git apply -R。有关更多信息,请参见Git 工具-隐藏和清理
现在让我们从一个仓库的历史记录中删除一个文件并将其添加到.gitignore(以防止重新提交)。
在继续之前,请确保已经安装了git filter-repo在这里阅读如何安装),并且已经有了本地的存储库副本(如果没有,请在这里查看如何克隆存储库)。
  1. Open GitBash and access the repository.

    cd YOUR-REPOSITORY
    
  2. (Optional) Backup the .git/config file.

  3. Run

    git filter-repo --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
    

    replace PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA with the path to the file you want to remove, not just its filename to:

    • Force Git to process, but not check out the entire history of every branch and tag.

    • Remove the specified file (as well as empty commits generated as a result)

    • Remove some configs (such as remote URL stored in the .git/config file)

    • Overwrite one's existing tags.

  4. Add the file with sensitive data to .gitignore

    echo "YOUR-FILE-WITH-SENSITIVE-DATA" >> .gitignore
    
    git add .gitignore
    
    git commit -m "Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore"
    
  5. Check if everything was removed from one's repository history, and that all branches are checked out. Only then move to the next step.

  6. Force-push the local changes to overwrite your repository on GitHub.com, as well as all the branches you've pushed up. A force push is required to remove sensitive data from your commit history. Read the first note at the bottom of this answer for more details one this.

    git push origin --force --all
    

选项2
使用BFG Repo-Cleaner。这比git filter-branch更快更简单。
例如,要删除一个包含敏感数据的文件并保留最新提交不变,请运行:
bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

要替换存储库历史记录中任何位置出现的“passwords.txt”文件中列出的所有文本,请运行以下命令:
bfg --replace-text passwords.txt

敏感数据移除后,必须将更改强制推送到GitHub。
git push --force

额外的:
在使用上述选项之一后:
  1. Contact GitHub Support.

  2. (If working with a team) Tell them to rebase, not merge, any branches they created off of one's old (tainted) repository history. One merge commit could reintroduce some or all of the tainted history that one just went to the trouble of purging.

  3. After some time has passed and you're confident that one had no unintended side effects, one can force all objects in one's local repository to be dereferenced and garbage collected with the following commands (using Git 1.8.5 or newer):

    git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
    
    git reflog expire --expire=now --all
    
    git gc --prune=now
    

替代方案

如果文件是在最新提交时添加的,并且还没有推送到GitHub.com,则可以删除该文件并修改提交:

  1. Open GitBash and access the repository.

    cd YOUR-REPOSITORY.l
    
  2. To remove the file, enter git rm --cached:

    git rm --cached GIANT_FILE
    # Stage our giant file for removal, but leave it on disk
    
  3. Commit this change using --amend -CHEAD:

    git commit --amend -CHEAD
    # Amend the previous commit with your change
    # Simply making a new commit won't work, as you need
    # to remove the file from the unpushed history as well
    
  4. Push one's commits to GitHub.com:

    git push
    # Push our rewritten, smaller commit
    

为了未来

为了防止敏感数据被曝光,其他良好的做法包括:

使用可视化程序提交更改。有各种替代方案(如GitHub Desktop, GitKraken, gitk等),跟踪更改可能会更容易。
避免使用全局命令git add .git commit -a。相反,使用git add 文件名git rm 文件名单独暂存文件。
使用git add --interactive单独审查和暂存每个文件中的更改。
使用git diff --cached审查已经暂存以进行提交的更改。只要不使用-a标志,这就是git commit将生成的确切差异。
在安全硬件(HSM盒子、硬件密钥-如Yubikey / Solokey)中生成秘密密钥,永远不离开它。
对团队进行x508培训。
注:

2
所以,它看起来像这样:
git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

从Git中删除跟踪文件的缓存,并将该文件添加到.gitignore列表中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接