此文章发布于23
个月前,部分信息可能已经过时
,请自行斟酌确认。
问题描述
每一次 git 提交修改的改变都会以文件的形式存储在本地项目根目录下的 .git 中,会在 .git/objects
下面形成一个 Blob(一段二进制数据)文件记录。
所以 git 仓库随着时间变化会自增长,直到大到我们拉取代码变得困难。
如何清理 git 中的大文件?
Git 仓库过大会导致哪些问题?
- git 仓库体积过大,占用电脑本地闪存的存储空间;
- clone git 仓库时,耗时过长,甚至完全 clone 不下来导致 git 报错;
- git pull 时会由于引用对象过多会报错,导致本地代码无法更新;
- 在切换分支的时候经常会出现 cpu 占满,内存占满的情况导致电脑死机。
解决方案1
推荐,速度快好用。
使用 bfg 工具:https://rtyley.github.io/bfg-repo-cleaner/
#先查询出大文件(查询方法见方案2)
#删除大文件
java -jar d:/bfg-1.14.0.jar --delete-files "*publish.zip" --no-blob-protection
#清理日志、压缩空间
git reflog expire --expire=now --all && git gc --prune=now --aggressive
#强制推送
git push origin --force --all
git remote prune origin
解决方案2
不推荐,太慢。
1、查看仓库大小
$ git count-objects -vH
2、查看大文件命令(使用 Git Bash 运行):
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
3、删除文件
命令如下,注意:一次只能处理一个文件/文件夹,如果有多个需要耐心处理。可以写多个文件空格分隔,像 Linux 一样,测试好像是可以的。
成功会显示 Rewrite xxxx(233/666)
如果显示 xxxxx unchanged说明 repo 里没有找到该文件,请检查路径和文件名是否正确。
$ git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch PR/ScmPR40.zip' --tag-name-filter cat -- --all
参数解释:filter-branch
是让 git 重写每一个分支,--force
假如遇到冲突也让git强制执行,--index-filter
选项指定重写的时候应该执行什么命令,要执行的命令紧跟在它的后面,在这里就是 git rm --cached --ignore-unmatch password.txt
,让 git 删除掉缓存的文件,如果有匹配的话。--prune-empty
选项告诉git,如果因为重写导致某些commit变成了空(比如修改的文件全部被删除),那么忽略掉这个commit。--tag-name-filter
表示对每一个tag如何重命名,重命名的命令紧跟在后面,当前的tag名会从标注输入送给后面的命令,用cat就表示保持tag名不变。
紧跟着的-- 表示分割符,最后的--all 表示对所有的文件都考虑在内。
4、git gc 命令压缩
git reflog expire --expire=now --all
git gc --prune=now
也有代码说要这样操作,我只执行了上面 2 个命令后再查空间占用就已经变小了。
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
rm -rf .git/refs/original/
#对git的reflog记录进行清空
git reflog expire --expire=now --all
git gc --prune=now
git gc --prune=now --aggressive
5、推送到服务器,清理远程仓库
git push origin --force --all
git remote prune origin
注意:清理完之后,每个人一定要删掉之前拉取的项目, 重新从git上拉项目。不要使用之前的项目了!否则会不降反升!
6、清理服务器缓存
如果有条件进入到 Gitlab 服务部署目录,可以对远程仓库进行确认和瘦身。(没有条件,没有尝试)
sudo su
cd ${gitlab项目部署目录}/git-data/repositories/{待清理的项目地址}
git count-objects -vH #此时还是旧的大小
git gc --prune=now #清理无效文件
git count-objects -vH #此时就和本地一样减小了
7、处理好后的干净库如何同步到所有参与开发的同学?
经过上述所有的操作得到一个干净的 git 库后,还需要避免其他有历史库的同学执行 push 操作,因为一旦执行 push 操作就会前功尽弃,导致陈旧的历史库再次污染到新的远程仓库中。所以我们需要让所有开发同学重新克隆仓库。