我想将一个Git项目放到GitHub上,但它包含某些包含敏感数据的文件(用户名和密码,例如capistrano的/config/deploy.rb)。
我知道可以将这些文件名添加到.gitignore中,但这并不会从Git中删除它们的历史记录。
我也不想通过删除/.git目录来重新开始。
有没有一种方法可以删除您Git历史记录中特定文件的所有痕迹?
我想将一个Git项目放到GitHub上,但它包含某些包含敏感数据的文件(用户名和密码,例如capistrano的/config/deploy.rb)。
我知道可以将这些文件名添加到.gitignore中,但这并不会从Git中删除它们的历史记录。
我也不想通过删除/.git目录来重新开始。
有没有一种方法可以删除您Git历史记录中特定文件的所有痕迹?
使用git filter-repo
工具(在GitHub上查看源代码)。
使用BFG Repo-Cleaner工具(它是开源的 - 在GitHub上查看源代码)。
git filter-repo
。在继续之前,请注意:git filter-repo
,则无法使用其他隐藏命令检索您的更改。在运行 git filter-repo
之前,我们建议取消隐藏您所做的任何更改。要取消隐藏您最后一组隐藏的更改,请运行 git stash show -p | git apply -R
。有关更多信息,请参见Git 工具-隐藏和清理。.gitignore
(以防止重新提交)。git filter-repo
(在这里阅读如何安装),并且已经有了本地的存储库副本(如果没有,请在这里查看如何克隆存储库)。
Open GitBash and access the repository.
cd YOUR-REPOSITORY
(Optional) Backup the .git/config
file.
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.
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"
Check if everything was removed from one's repository history, and that all branches are checked out. Only then move to the next step.
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
git filter-branch
更快更简单。bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA
bfg --replace-text passwords.txt
git push --force
(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.
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,则可以删除该文件并修改提交:
Open GitBash and access the repository.
cd YOUR-REPOSITORY.l
To remove the file, enter git rm --cached
:
git rm --cached GIANT_FILE
# Stage our giant file for removal, but leave it on disk
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
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
将生成的确切差异。当一个力量推动时,它会重写存储库历史记录,从提交历史记录中删除敏感数据。这可能会覆盖其他人基于其工作的提交。
对于这个答案,使用了一些 GitHub 帖子的内容:
git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore
.gitignore
列表中。