删除敏感文件及其从git历史记录中的提交
-
22-08-2019 - |
题
我想在github上放置一个git项目,但它包含具有敏感数据的某些文件(用户名和密码,例如capistrano的 /config/deploy.rb)。
我知道我可以将这些文件名添加到 .gitignore, ,但这不会删除他们在git中的历史。
我也不想通过删除/.git目录重新开始。
有没有办法去除 全部 您的git历史记录中特定文件的痕迹?
解决方案
出于所有实际目的, 第一的 你应该担心的是 更改密码! 从您的问题中尚不清楚您的git存储库是否完全是本地的,还是您在其他地方是否有远程存储库;如果它是遥远的,并且没有与他人相处,那么您会有问题。如果有人在修复此问题之前先将该存储库克隆过,则他们将在本地计算机上拥有您的密码副本,并且您无法强迫它们更新到您的“固定”版本,并从历史记录中消失。您可以做的唯一安全的事情就是将密码更改为所使用的其他地方。
这样做,这就是解决方案的方法。 Github完全回答了这个问题作为常见问题:
注意Windows用户: :在此命令中使用双引号(“)而不是单身
git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force
请记住,一旦将此代码推到了像Github这样的远程存储库后,其他人将远程存储库克隆起来,您现在就处于重写历史记录的情况。当其他人在此之后尝试拉下您的最新更改时,他们会收到一条消息,表明这些更改无法应用,因为它不是快速的。
为了解决此问题,他们必须删除现有存储库并重新粘结它,或遵循“从上游恢复”中的说明 git-rebase manpage.
将来,如果您不小心对敏感信息进行一些更改,但您会注意到 前 推到远程存储库,有一些更轻松的修复程序。如果您上次提交是添加敏感信息的提交,则可以简单地删除敏感信息,然后运行:
git commit -a --amend
这将通过您所做的任何新更改进行修改以前的提交,包括使用 git rm
. 。如果这些更改在历史记录中更远,但仍然没有推到远程存储库,则可以进行交互式重新构想:
git rebase -i origin/master
自从您与远程存储库的最后一个共同祖先以来,您可以通过您所做的提交打开编辑器。将“选择”更改为“编辑”,以代表具有敏感信息的提交的任何行,然后保存和退出。 git将段落穿越这些变化,并让您处于可以:
$EDITOR file-to-fix
git commit -a --amend
git rebase --continue
对于每个更改,都有敏感信息。最终,您最终会回到分支上,并且可以安全地推动新的更改。
其他提示
更改密码是一个好主意,但是对于从存储库的历史记录中删除密码的过程,我建议您使用 bfg repo-cleaner, ,更快,更简单的替代方案 git-filter-branch
明确设计用于从GIT存储库中删除私人数据。
创建一个 private.txt
文件列出要删除的密码等的文件(每行一个条目),然后运行此命令:
$ java -jar bfg.jar --replace-text private.txt my-repo.git
将扫描存储库历史记录中的所有阈值大小(默认情况下为1MB)的所有文件,并将扫描任何匹配的字符串(这不在您的 最新的 提交)将被“ ***删除***”的字符串替换。然后您可以使用 git gc
清理死亡数据:
$ git gc --prune=now --aggressive
BFG通常比运行快10-50倍 git-filter-branch
并且这些选项是简化的,并围绕这两个常见用例量身定制:
- 去除 疯狂的大文件
- 去除 密码,凭据 & 其他 私人数据
全面披露:我是BFG回购器的作者。
我建议 这个脚本 大卫·安德希尔(David Underhill)的作品对我来说像魅力。
它添加了这些命令,此外,Natacado的过滤器分支清理了它留下的烂摊子:
rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune
完整剧本(全部归功于大卫·安德希尔(David Underhill))
#!/bin/bash
set -o errexit
# Author: David Underhill
# Script to permanently delete files/folders from your git repository. To use
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2
if [ $# -eq 0 ]; then
exit 0
fi
# make sure we're at the root of git repo
if [ ! -d .git ]; then
echo "Error: must run this script from the root of a git repository"
exit 1
fi
# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD
# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune
如果更改为以下内容,则最后两个命令可能会更好:
git reflog expire --expire=now --all && \
git gc --aggressive --prune=now
如果您推到github,则强力推动还不够,请删除存储库或联系人支持
即使您之后强迫推一秒钟,也不够,如下所述。
唯一有效的行动方案是:
是什么像密码一样泄漏了可更改的凭据?
- 是:立即修改密码,并考虑使用更多OAuth和API键!
否(裸照):
您是否在乎存储库中的所有问题都会受到核算?
- 否:删除存储库
是的:
- 联系支持
- 如果泄漏对您至关重要,以至于您愿意获得一些存储库的停机时间以使其不太可能泄漏, 使其私密 当您等待GitHub支持回复您时
稍后推一秒的力是不够的,因为:
Github长期以来一直在悬空。
GitHub的工作人员确实有权删除这种悬挂的提交,但如果您与他们联系。
我的第一手 将所有GitHub提交电子邮件上传到回购 他们要求我把它取下来,所以我做到了,他们做了一个
gc
. 。拉包含数据的请求 但是必须删除: :由于此,该回购数据仍可在初次撤离后一年内访问。可以通过:
- 提交Web UI: https://github.com/cirosantilli/test-dangling/commit/53df36c09f092bbbb59f2faa34eba15cd89ef8e83 (Wayback Machine)
- API: https://api.github.com/repos/cirosantilli/test-dangling/commits/53DF36C09F092BBBBBBBB59F2FAA34EBA15CD89EF89EF8E83 (Wayback Machine)
在该提交中获取源的一种方便方法是使用下载zip方法,该方法可以接受任何参考,例如: https://github.com/cirosantilli/myrepo/archive/sha.zip
可以通过:
- 使用
type": "PushEvent"
. 。例如我的: https://api.github.com/users/cirosantilli/events/public (Wayback Machine) - 有时更方便地查看试图删除内容的拉动请求的shas
- 使用
有像 http://ghtorrent.org/ 和 https://www.githubarchive.org/ 定期将github数据池并存储在其他地方。
我找不到他们是否会刮擦实际的提交差异,这不太可能是因为有太多数据,但是从技术上讲是可能的,NSA和朋友可能有过滤器只能存档与人或感兴趣的人相关的东西。
但是,如果您删除存储库而不是仅仅强制推动,则提交确实会立即从API中消失,并给出404,例如 https://api.github.com/repos/cirosantilli/cirosantilli/test-dangling-delete/commits/8c08448b5fbfbf0f891696819f3b2b2b2b2b2b2b2b2b2b2b2b2b2 d653f7a3824 即使您重新创建了具有相同名称的另一个存储库,这也有效。
为了测试这一点,我创建了一个仓库: https://github.com/cirosantilli/test-dangling 并做到了:
git init
git remote add origin git@github.com:cirosantilli/test-dangling.git
touch a
git add .
git commit -m 0
git push
touch b
git add .
git commit -m 1
git push
touch c
git rm b
git add .
git commit --amend --no-edit
git push -f
也可以看看: 如何删除Github的悬挂式提交?
要明确:公认的答案是正确的。先尝试一下。但是,对于某些用例,这可能是不必要的复杂,尤其是如果您遇到令人讨厌的错误,例如“致命:不良修订 - Prune-empty”,或者真的不在乎您的存储库历史。
另一种选择是:
- CD到Project的基本分支
- 删除敏感代码 /文件
- RM -RF .git/#从您的代码中删除所有GIT信息
- 转到github并删除您的存储库
- 按照本指南按照通常的方式将代码推向新的存储库 -https://help.github.com/articles/adding-an--cropting-project-to-github-using-command-line/
当然,这将删除所有提交历史分支机构,以及您的GitHub存储库和本地GIT存储库中的问题。如果这是不可接受的,您将必须使用替代方法。
称其为核选择。
这是我在Windows中的解决方案
git filter-branch - 树滤波器“ rm -f'fileedir/fileName'”
git推动 - 力量
确保路径正确,否则行不通
我希望它有帮助
利用 过滤器分支:
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *file_path_relative_to_git_repo*' --prune-empty --tag-name-filter cat -- --all
git push origin *branch_name* -f
您可以使用 git forget-blob
.
用法非常简单 git forget-blob file-to-forget
. 。您可以在这里获取更多信息
它将从您的历史上的所有提交中消失,返回,标签等
我时不时地遇到了相同的问题,每次我都必须回到这篇文章和其他帖子时,这就是为什么我自动化该过程的原因。
积分对Stack Overflow的贡献者的学分,这使我能够将其放在一起
我不得不做几次迄今为止。请注意,这仅适用于1个文件。
获取修改文件的所有提交的列表。底部的一个将是第一个提交:
git log --pretty=oneline --branches -- pathToFile
要从历史记录中删除文件,请使用第一个提交SHA1和从上一个命令中的文件归档的路径,然后将其填充到此命令中:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..
因此,看起来像这样:
git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore
从git中删除用于跟踪文件的缓存,然后将该文件添加到
.gitignore
列表
在我的Android项目中 admob_keys.xml 作为分离的XML文件 app/src/main/res/values/ 文件夹。为了删除此敏感的文件,我在下面使用的脚本完美工作。
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch app/src/main/res/values/admob_keys.xml' \
--prune-empty --tag-name-filter cat -- --all