我想在GitHub上放一个Git项目,但它包含一些带有敏感数据的文件(用户名和密码,比如/ config /deploy.rb for capistrano)。
我知道我可以将这些文件名添加到.gitignore,但这不会删除他们在Git中的历史记录。
我也不想通过删除/.git目录重新开始。
有没有办法删除Git历史记录中特定文件的所有痕迹?
出于所有实际目的,您首先要担心的是改变您的密码!从您的问题中不清楚您的git存储库是完全本地的还是其他地方还有远程存储库;如果它是远程的并且没有从其他人那里获得安全,那么你就有问如果有人在你修复它之前克隆了那个存储库,那么他们就会在你的本地机器上有你的密码副本,并且你无法强迫他们更新到你的“固定”版本,而它已经从历史中删除了。您可以做的唯一安全的事情是将密码更改为您使用它的任何地方。
有了这个,这是如何解决它。 GitHub answered exactly that question as an FAQ:
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
完成的整个文件删除。如果更改在历史记录中进一步返回但仍未推送到远程存储库,则可以执行交互式rebase:
git rebase -i origin/master
这将打开一个编辑器,其中包含您自上次使用远程存储库的共同祖先以来所做的提交。在表示具有敏感信息的提交的任何行上将“选择”更改为“编辑”,然后保存并退出。 Git将会介绍这些变化,并将您留在可以:
$EDITOR file-to-fix
git commit -a --amend
git rebase --continue
对于敏感信息的每次更改。最终,您将最终回到您的分支上,并且您可以安全地推送新的更改。
所以,它看起来像这样:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..
从git中删除跟踪文件的缓存,并将该文件添加到
git rm --cached /config/deploy.rb echo /config/deploy.rb >> .gitignore
列表中
在我的android项目中,我将admob_keys.xml作为分隔的xml文件放在app / src / main / res / values /文件夹中。要删除这个敏感文件,我使用下面的脚本并完美地工作。
.gitignore
更改密码是一个好主意,但是对于从repo历史中删除密码的过程,我推荐使用BFG Repo-Cleaner,这是一种更快,更简单的git-filter-branch
替代方案,专门用于从Git repos中删除私有数据。
创建一个private.txt
文件,列出要删除的密码等(每行一个条目),然后运行以下命令:
$ java -jar bfg.jar --replace-text private.txt my-repo.git
将扫描您的仓库历史记录中阈值大小(默认为1MB)的所有文件,并且任何匹配的字符串(不在您的最新提交中)将替换为字符串“*** REMOVED ***”。然后,您可以使用git gc
清除死数据:
$ git gc --prune=now --aggressive
BFG通常比运行git-filter-branch
快10-50倍,并且选项经过简化并围绕这两个常见用例进行了定制:
完全披露:我是BFG Repo-Cleaner的作者。
我推荐David Underhill的this script,对我来说就像一个魅力。
除了natacado的filter-branch之外,它还添加了这些命令来清理它留下的混乱:
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,强制推送是不够的,删除存储库或联系支持
即使您之后强行推动一秒钟,也不够,如下所述。
唯一有效的行动方针是:
强迫推迟一秒钟是不够的,因为:
gc
。拉取包含数据have to be deleted however的请求:由于此原因,在最初删除后一年内仍然可以访问该回购数据。
通过以下方式可以看到悬空提交:
提交Web UI:https://github.com/cirosantilli/test-dangling/commit/53df36c09f092bbb59f2faa34eba15cd89ef8e83(Wayback machine)
API:https://api.github.com/repos/cirosantilli/test-dangling/commits/53df36c09f092bbb59f2faa34eba15cd89ef8e83(Wayback machine)
在该提交中获取源的一种便捷方法是使用下载zip方法,该方法可以接受任何引用,例如:https://github.com/cirosantilli/myrepo/archive/SHA.ziptype": "PushEvent"
列出API事件。例如。我的:https://api.github.com/users/cirosantilli/events/public(Wayback machine)
通过查看试图删除内容的拉取请求的SHA,有时更方便但是,如果删除存储库而不是仅强制推送,则提交甚至会立即从API中消失并提供404,例如, https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824即使您重新创建具有相同名称的另一个存储库,这也可以工作。
为了测试这一点,我创建了一个回购:https://github.com/cirosantilli/test-dangling并做了:
git init
git remote add origin [email protected]: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仓库和本地git仓库的问题。如果这是不可接受的,您将不得不使用替代方法。
称之为核选项。
这是我在windows中的解决方案
git filter-branch --tree-filter“rm -f'storeir / filename'”HEAD
git push --force
确保路径正确,否则它将无法正常工作
我希望它有所帮助
使用filter-branch:
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
。
用法非常简单qazxswpoi。你可以在这里获得更多信息
git forget-blob file-to-forget
它将从您的历史记录,reflog,标签等中的所有提交中消失
我时不时遇到同样的问题,每次我都要回到这个帖子和其他人,这就是我自动化流程的原因。
来自Stack Overflow的贡献者的积分让我可以把它放在一起
到目前为止,我不得不这样做几次。请注意,这一次仅适用于1个文件。
git log --pretty=oneline --branches -- pathToFile