Git 如何永久删除文件 ( 包括历史记录 )
2013-12-05 20:14 by shines77,~ 阅读 ,~ 1~ 评论 ,~ 收藏 ,~ 编辑
有些时候不小心上传了一些敏感文件 ( 例如密码 ), 或者不想上传的文件 ( 没及时或忘了加到 .gitignore 里的 ),
而且上传的文件又特别大的时候 , 这将导致别人 clone 你的代码或下载 zip 包的时候也必须更新或下载这些无用的文件 ,
因此 , 我们需要一个方法 , 永久的删除这些文件 ( 包括该文件的历史记录 ).
首先 , 可以参考 github 的帮助 :
https://help.github.com/articles/remove-sensitive-data
步骤一 :~ 从你的资料库中清除文件
以 Windows 下为例 (Linux 类似 ), 打开项目的 Git Bash, 使用命令 :~
git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch path- or -your-remove-file' --prune-empty --tag-name-filter cat -- --all
其中 ,~ path-to-your-remove-file ~ 就是你要删除的文件的相对路径 ( 相对于 git 仓库的跟目录 ), 也可以替换成你要删除的文件全路径名。
注意,上述指令只能对需要删除的文件起作用!不要对有用的文件用上述指令。
如果你要删除的文件很多 , 可以写进一个 .sh 文件批量执行 , 如果文件或路径里有中文 , 由于 MinGW 或 CygWin 对中文路径设置比较麻烦 , 你可以使用通配符 * 号 , 例如 : sound/music_*.mp3, 这样就把 sound 目录下以 music_ 开头的 mp3 文件都删除了 .
例如这样 ,~ del-music-mp3.sh :
#!/bin/ bash
# git filter -branch --force --index-filter 'git rm --cached --ignore-unmatch projects/Moon.mp3' --prune-empty --tag-name-filter cat -- -- all
# git filter -branch --force --index-filter 'git rm --cached --ignore-unmatch sound/Music_*.mp3' --prune-empty --tag-name-filter cat -- --all
~ 如果你看到类似下面这样的 , 就说明删除成功了 :
Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 ( 266 / 266 )
# Ref 'refs/heads/master' was rewritten
如果显示 xxxxx unchanged, 说明 repo 里没有找到该文件 , 请检查路径和文件名是否正确 .
注意 :~ 补充一点 , 如果你想以后也不会再上传这个文件或文件夹 , 请把这个文件或文件夹添加到 .gitignore 文件里 , 然后再 push 你的 repo.
步骤二 : 推送我们修改后的 repo
以强制覆盖的方式推送你的 repo, 命令如下 :
git push origin master --force
这个过程其实是重新上传我们的 repo, 比较耗时 , 虽然跟删掉重新建一个 repo 有些类似 , 但是好处是保留了原有的更新记录 , 所以还是有些不同的 . 如果你实在不在意这些更新记录 , 也可以删掉重建 , 两者也差不太多 , 也许后者还更直观些 .
执行结果类似下面 :
Counting objects: 4669 , done .
Delta compression using up to 4 threads.
Compressing objects: 100 % ( 4352 / 4352 ), done .
Writing objects: 100 % ( 4666 / 4666 ), 35.16 MiB | 51 KiB/s, done .
Total 4666 (delta 1361 ), reused 0 (delta 0 )
To https://github.com/defunkt/github-gem.git
+ beb839d...81f21f3 master -> master (forced update)
~ 步骤三 :~ 清理和回收空间
虽然上面我们已经删除了文件 , 但是我们的 repo 里面仍然保留了这些 objects, 等待垃圾回收 (GC), 所以我们要用命令彻底清除它 , 并收回空间 .
命令如下 :
rm -rf .git/refs/original/
git reflog expire --expire=now -- all
git gc --prune= now
Counting objects: 2437, done.
# Delta compression using up to 4 threads.
# Compressing objects: 100% (1378/1378), done.
# Writing objects: 100% (2437/2437), done.
# Total 2437 (delta 1461), reused 1802 (delta 1048)
git gc --aggressive --prune=now
Counting objects: 2437, done.
# Delta compression using up to 4 threads.
# Compressing objects: 100% (2426/2426), done.
# Writing objects: 100% (2437/2437), done.
# Total 2437 (delta 1483), reused 0 (delta 0)