我想把一个Git项目放在GitHub上,但它包含某些具有敏感数据的文件(用户名和密码,如/config/deploy。卡皮斯特拉诺的Rb)。

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

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

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


当前回答

使用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

其他回答

在我的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

For all practical purposes, the first thing you should be worried about is CHANGING YOUR PASSWORDS! It's not clear from your question whether your git repository is entirely local or whether you have a remote repository elsewhere yet; if it is remote and not secured from others you have a problem. If anyone has cloned that repository before you fix this, they'll have a copy of your passwords on their local machine, and there's no way you can force them to update to your "fixed" version with it gone from history. The only safe thing you can do is change your password to something else everywhere you've used it.


有了这些,下面是如何解决它的方法。GitHub在FAQ中回答了这个问题:

Windows用户注意:在此命令中使用双引号(")而不是单引号

git filter-branch --index-filter \
'git update-index --remove PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

2019年更新:

这是FAQ中的当前代码:

  git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" \
  --prune-empty --tag-name-filter cat -- --all
  git push --force --verbose --dry-run
  git push --force

请记住,一旦您将这段代码推到GitHub等远程存储库,其他人已经克隆了该远程存储库,您现在就处于重写历史的情况下。在此之后,当其他人尝试下拉您的最新更改时,他们将收到一条消息,指示无法应用更改,因为它不是快进。

为了解决这个问题,他们必须删除现有的存储库并重新克隆它,或者遵循git-rebase手册中“从UPSTREAM REBASE中恢复”的说明。

提示:执行git rebase—交互式


将来,如果您不小心提交了一些涉及敏感信息的更改,但在推送到远程存储库之前注意到了这些更改,有一些更容易的修复方法。如果上次提交是添加敏感信息的提交,您可以简单地删除敏感信息,然后运行:

git commit -a --amend

这将使用您所做的任何新更改来修改之前的提交,包括使用git rm删除整个文件。如果更改在历史上更早,但仍然没有推送到远程存储库,您可以进行交互式rebase:

git rebase -i origin/master

这将打开一个编辑器,其中包含自与远程存储库的最后一个共同祖先以来所做的提交。在表示提交敏感信息的任何行上,将“pick”更改为“edit”,然后保存并退出。Git将遍历这些更改,并将您留在以下位置:

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

对于每个具有敏感信息的更改。最终,您将回到您的分支,并且您可以安全地推动新的更改。

使用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 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>..

我推荐大卫·安德希尔的这个剧本,对我来说很有魅力。

它在natacado的filter分支中添加了这些命令来清理它留下的混乱:

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune

完整剧本(全部由大卫·安德希尔提供)

#!/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