我想在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支持回复您时

稍后推一秒的力是不够的,因为:

但是,如果您删除存储库而不是仅仅强制推动,则提交确实会立即从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”,或者真的不在乎您的存储库历史。

另一种选择是:

  1. CD到Project的基本分支
  2. 删除敏感代码 /文件
  3. RM -RF .git/#从您的代码中删除所有GIT信息
  4. 转到github并删除您的存储库
  5. 按照本指南按照通常的方式将代码推向新的存储库 -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. 。您可以在这里获取更多信息

https://ownyourbits.com/2017/01/18/completely-remove-a-file-file-from-a-git-repository-with-git-forget-blob/

它将从您的历史上的所有提交中消失,返回,标签等

我时不时地遇到了相同的问题,每次我都必须回到这篇文章和其他帖子时,这就是为什么我自动化该过程的原因。

积分对Stack Overflow的贡献者的学分,这使我能够将其放在一起

我不得不做几次迄今为止。请注意,这仅适用于1个文件。

  1. 获取修改文件的所有提交的列表。底部的一个将是第一个提交:

    git log --pretty=oneline --branches -- pathToFile

  2. 要从历史记录中删除文件,请使用第一个提交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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top