如果你对外开源的代码中出现了敏感信息(例如你将私钥上传到了仓库中),你可能需要考虑将这个文件从 git 的历史记录中完全删除掉。
第一步:删除本地历史记录
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch key.xml' --prune-empty --tag-name-filter cat -- --all
其中 key.xml 是本来不应该上传的文件,于是使用此命令彻底删除。后面的命令 --tag-name-filter 指所有相关的标签都需要更新。
如果要删除目录
git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch keys' --prune-empty --tag-name-filter cat -- --all rm -rf .git/refs/original/ git reflog expire --expire=now --all git fsck --full --unreachable git repack -A -d #关键是这个命令,执行重新打包,并且未被引用的文件将不出现在新包中,执行完成后.git/objects/pack/pack-*.pack文件将被压缩到很小 git gc --aggressive --prune=now
删除文件夹时需要额外带一个 -r 选项,并指定文件夹名称,这里的例子是 keys目录。
第二步:强制推送到远端仓库
刚刚我们的操作仅仅发生在本地仓库,敏感信息需要删除的仓库通常都在远端,于是我们一定要将修改推送到远端仓库。
需要推送的目标分支包括我们所有长期维护的分支,这通常就包括了 master
分支和所有的标签。
git push origin master:master --tags --force
示例(如果有多分支,每个分支都要执行)
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.jar' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch target' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch classes' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch .settings' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch test' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.classpath' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.project' --prune-empty --tag-name-filter cat -- --all ;\ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *.class' --prune-empty --tag-name-filter cat -- --all ;\ rm -rf .git/refs/original/;\ git reflog expire --expire=now --all ;\ git fsck --full --unreachable;\ git repack -A -d ;\ git gc --aggressive --prune=now;\ git push origin master:master --tags --force