Git永久删除库中的文件

2 minute read

如果使用git不小心提交了一个类似debug或者.swp的临时文件,即使用git rm删除,只会向版本库中新增一条删除记录,之前提交的文件物理上还保存在版本库中,每次用git clone的时候都会下载,时间久了,这样的文件多了,就会使得整个版本库庞大无比,所以需要找到将这些文件从版本库中物理删除的办法。

解决办法

 1#1. 确定文件从哪个commit引入的
 2git log --pretty=oneline --branches -- bigfile
 3
 4#2. 让git重写每一个分支, 删除bigfile
 5git filter-branch --force --index-filter \
 6"git rm --cached --ignore-unmatch BIGFILE" | "git rm -r --cached --ignore-unmatch BIGDIR" \
 7--prune-empty --tag-name-filter cat -- --all
 8
 9#3. 推送修改
10git push --all --force
11# 清除本地的git内存与记录等
12git for-each-ref --format='delete %(refname)' refs/original
13git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
14git reflog expire --expire=now --all
15git gc --prune=now
16git push origin --force --all
17git push origin --force --tags

参数说明

filter-branch 是让git重写每一个分支,

--force 假如遇到冲突也让git强制执行, --index-filter 选项指定重写的时候应该执行什么命令,要执行的命令紧跟在它的后面,在这里就是git rm --cached --ignore-unmatch bigfile ,让git删除掉缓存的文件,如果有匹配的话。

--prune-empty 选项告诉git,如果因为重写导致某些commit变成了空(比如修改的文件全部被删除),那么忽略掉这个commit。

--tag-name-filter 表示对每一个tag如何重命名,重命名的命令紧跟在后面,当前的tag名会从标注输入送给后面的命令,用cat就表示保持tag名不变。

紧跟着的-- 表示分割符,最后的--all 表示对所有的文件都考虑在内。