从Git历史记录中删除敏感文件及其提交

我想在GitHub上放一个Git项目,但它包含某些带有敏感数据的文件(用户名和密码,例如capistrano的/config/deploy.rb)。

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

我也不想重新开始删除/.git目录。

有没有办法删除Git历史记录中特定文件的所有痕迹?


出于所有实际目的,您应该担心的第一件事是更改您的密码! 从你的问题中不清楚你的git仓库是完全本地的还是你在其他地方有一个远程仓库; 如果它是远程的并且没有从其他人那里获得保护,那么你有问题 如果有人在解决此问题之前克隆了该存储库,则他们将在其本地计算机上拥有密码的副本,并且无法强制他们更新到历史记录中的“固定”版本。 您可以做的唯一安全的事情就是将您的密码更改为您使用它的任何地方。


除此之外,以下是如何解决它。 GitHub正是将这个问题作为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联机帮助页中的“RECOVERING FROM UPSTREAM REBASE”下的说明进行操作。


在将来,如果您意外地对敏感信息进行了一些更改,但推送到远程存储库之前您注意到了,则有一些更简单的修复方法。 如果您最后一次提交是添加敏感信息的提交,您可以简单地删除敏感信息,然后运行:

git commit -a --amend

这将修改您之前做出的任何新更改,包括使用git rm完成的整个文件删除。 如果这些更改进一步回溯到历史记录中,但仍未推送到远程存储库,则可以执行交互式转化:

git rebase -i origin/master

这会打开一个编辑器,其中包含自从您与远程存储库上次共同祖先以来所做的提交。 在代表提交敏感信息的任何行上将“pick”更改为“edit”,然后保存并退出。 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)下的所有文件,并且任何匹配的字符串(不在您最新的提交中)将被替换为字符串“*** REMOVED ***”。 然后你可以使用git gc清除死信息:

$ git gc --prune=now --aggressive

BFG的运行速度通常比运行git-filter-branch快10-50倍,并且这些选项被简化并根据这两种常见用例进行定制:

  • 删除疯狂的大文件
  • 删除密码,凭证和其他私人数据
  • 充分披露:我是BFG Repo-Cleaner的作者。


    我推荐David Underhill编写的剧本,对我来说就像是一种魅力。

    它在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
    
    链接地址: http://www.djcxy.com/p/19459.html

    上一篇: Remove sensitive files and their commits from Git history

    下一篇: git checkout: untracked working tree files would be overwritten by checkout