你之前是否已经提交了SSH私钥、密码文件或包含敏感数据的配置文件到你的存储库?
原文地址:itextpdf.com/en/blog/tec…
原文作者:itextpdf.com/en/blog
发布时间:
介紹
你之前是否已经提交了一个SSH私钥、密码文件或包含敏感数据的配置文件到你的存储库?如果你没有,我建议你在继续阅读这篇博文之前,先试试这个。
对于我们其他人来说。不要惊慌!深吸一口气,从桌子上站起来,走动几分钟。准备好了吗?好了,我们开始吧!
我们的目标是彻底清除 Git 仓库中的一个文件,以掩盖你可怕的错误。你想成为那个将AWS密钥提交到GitHub公共仓库的人,却在24小时后发现约2000美元被用来挖比特币吗?
几种方法
简单的 git rm passwords.txt 是不行的,因为该文件仍然存在于之前的所有提交中。根据文件的位置,你可以使用几种方法。在此,按照复杂程度递增的顺序,对每个场景进行概述。
注意:
- 所有这些方法都假定你熟悉控制台命令。
- 这些方法是为 Linux 而写的,但在 OS X 上也可以使用,如果你使用 Git Bash,甚至可以在 Windows 上使用。
- 如果你已经推送了你的修改,那么事情可能会变得复杂。
- 如果你是一个单独的开发者,就去做吧。但如果你在一个团队中工作,那么先和他们商量一下。
- 如果你的代码(有不想要的文件)已经公开了(GitHub,BitBucket,......),那么你可能就不走运了。但请继续阅读,直到最后。
情况1:文件在最后一次提交中,而你还没有推送出去。
1. 你想把文件保存在本地
修改上次提交的内容,将该文件从版本库中删除,并将其添加到.gitignore中,防止再次被意外添加。
git rm --cached $FILE
echo $FILE >> .gitignore
git add .gitignore
git commit --amend --no-edit
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git reflog expire 和 git gc 命令会强制进行垃圾收集,以防止文件在仓库中的某个地方悬空。
2. 你不想把文件保存在本地
修改上次提交的内容即可。
git rm $FILE
git commit --amend --no-edit
git reflog expire --expire=now --all && git gc --prune=now --aggressive
情况2:文件在历史上比较靠后,而你还没有推送过。
解决办法1:BFG Repo-Cleaner。
在这里下载'BFG Repo-Cleaner'。这款工具号称比其他方法快10-720倍,但是你不能指定子目录,它会删除任何目录中所有同名的文件。
通常BFG Repo-Cleaner会保护你最近的提交,但如果你知道你在做什么(你知道,对吧?),那么你给它选项--no-blob-protection,这有点像在说,做我想做的,不要保护我的错误。
java -jar bfg.jar --delete-files $FILE --no-blob-protection .
rm $FILE
git reflog expire --expire=now --all && git gc --prune=now --aggressive
解决办法2:互动式重垒
交互式的rebase可以让你回溯历史,重做提交,就像他们一开始是正确的一样。听起来像作弊吗?也许是吧。但你想删除那个文件,你有能力做到这一点。
这条命令在 $(...)里面有一个子壳:它找到文件被添加的第一个提交,甚至考虑到文件的重名。然后在$(...)外面的命令会在该提交的父提交(~)处开始交互式的rebase。
git rebase --interactive \
$(git log --follow --find-renames=40% --diff-filter=A --format=%H -- $FILE)~
编辑git-rbase-todo文件:将第一条命令从pick改为edit。
复制到剪贴板 编辑 7b0a4be987 增加一个新的表格宽度测试。 pick 38737174a7 避免在不合适的时候使用FontProgram#getBaseName方法,更新文档。 选取66f95dd41b通用读取字节以进行woff格式转换。
edit 7b0a4be987 Add a new table width tests
pick 38737174a7 Avoid FontProgram#getBaseName method usage when it's not appropriate, update documentation
pick 66f95dd41b Generalize reading of bytes for woff format conversion
# Rebase d1613dff58..66f95dd41b onto d1613dff58 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
然后保存并关闭编辑器。Rebase 会将提交的内容回滚到添加不需要的文件的提交。
git rm $FILE
echo $FILE >> .gitignore
git add .gitignore
git commit --amend --no-edit
git rebase --continue
git reflog expire --expire=now --all && git gc --prune=now --aggressive
解决方案3:Git filter-branch
这将在每次提交时运行一个在--tree-filter中指定的脚本(例如:删除某个文件)。这真的很慢!因为它必须检查每一次提交,运行脚本,提交,然后继续下一次提交。这是因为它必须检查每一个提交,运行脚本,提交,然后继续下一个提交。当在违规提交和 HEAD 之间有标签或合并提交时,或者当违规文件存在于多个分支中时,可以使用这个方法。换句话说,作为最后的手段使用。
在这个脚本中,我用同样的方法找到第一个添加了不需要的文件的提交,然后我只在该提交的父分支上运行过滤器,直到当前分支的HEAD。git for-each-ref 命令会清理这些备份分支,因为我们真的很想摆脱那个讨厌的文件。--tag-name-filter cat 将确保任何标签都会随着提交而移动。
git filter-branch -f \
--prune-empty \
--tag-name-filter cat \
--tree-filter 'rm -f $FILE' \
$(git log --follow --find-renames=40% --diff-filter=A --format=%H -- $FILE)~..HEAD
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all && git gc --prune=now --aggressive
如果你想为整个仓库做(你真的不应该!)。
git filter-branch -f \
--prune-empty \
--tag-name-filter cat \
--tree-filter 'rm -f $FILE' \
-- --all
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all && git gc --prune=now --aggressive
场景3:你已经推送了
- 我不厌其烦地重复这一点:首先与你的团队的其他成员协商!!!。如果你不这样做,你会让他们的生活变得很痛苦。
- 其次,在你做其他事情之前,先对仓库进行备份。
- 然后。做个备份!
- 我不知道我是否已经提到过,但是你真的,真的确定你已经做了备份吗?
- 使用上面描述的方法之一来删除文件。
- 强行推送,但要知道你在做什么,要知道后果,因为如果你没有备份,就没有办法回去。
--force-with-lease实际上应该是那里的默认值,因为它首先会检查你不会覆盖其他人的工作。也可以参考Atlassian博客的精彩解释。
git push --force-with-lease origin $BRANCH
情况4:提交的内容已经在GitHub上了。
在这种情况下,即使在强制推送之后,仍然存在着有人可以访问不想要的文件的风险。
有两种方法可以做到这一点。
-
如果他们做了一个fork或者克隆版本库: 强制推送只会更新我们的版本库,不会更新fork/克隆版本。
-
如果他们碰巧知道添加文件的提交的确切哈希值(可能是他们写下来的,也可能是网页还在他们的浏览器缓存中),通过URL:
https://github.com/$USER/$REPO/commit/$COMMIT。
GitHub可能会在一段时间后垃圾回收缓存的视图,但这并不靠谱。
最好的办法是联系 GitHub 支持,告诉他们版本库和违规提交,他们会手动删除缓存的视图。
接下来该怎么做呢?
在后续的博文中,我将解释一些在iText软件公司使用的最佳实践来处理我们项目中需要的敏感文件。
通过www.DeepL.com/Translator (免费版)翻译