git 仓库越来越大,如何清理?

4,163 阅读5分钟

发现项目越来越大,主要是git历史提交记录占用很大空间

可以查看项目根目录下\ .git\objects\pack 这个目录所有文件的大小,该目录下的文件会保留着历史所有提交数据,并不会随着文件的删除而删除该历史提交记录,所以导致项目变得越来越大

git仓库过大会导致哪些问题?

  1. git仓库体积过大,占用电脑本地闪存的存储空间;

  2. clone git仓库时,耗时过长,甚至完全clone不下来导致git报错;

  3. git pull时会由于引用对象过多会报错,导致本地代码无法更新;

  4. 在切换分支的时候经常会出现cpu占满,内存占满的情况导致电脑死机;

多种解决方案:

方案一:不建议

删除远程仓库并且删除本地项目下的.git文件夹,然后执行git init之后重新推送到新仓库,这会导致历史commit记录全都被删除,如果今后想回滚到某一次commit那就没办法了,所以这种办法要慎重。 (注意:所有分支记得全部本地备份,重新全部推送到远程)

方案二:不建议

新创建仓库,把原项目除了node_modules和.git文件夹,其他文件全部拷贝到新仓库,注意: 需要把所有分支都要这么执行一次,比较繁琐,也没有commit提交记录,很不建议,不推荐。

方案三:不是很建议

用filter-branch去做git仓库的清理, 优化git仓库历史提交记录, 操作耗时比较长,效率不高,容易出错。

方案四:强烈推荐(需要有java开发环境)

使用BFG工具优化,专注做git仓库清理工作的工具, 特点: 快~、好用~、功能强大、使用简单。

分析哪些文件比较大

实战项目: ***管理系统

  • 先查看下 pack 的空间大小
git count-objects -v

优化前:OA \ .git\objects\pack 目录大小: 514MB

对历史提交文件大小排序分析

在git bash窗口执行下面这段命令会依次对历史提交中的文件大小进行排序,可以查看哪些文件比较大

git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| sed -n 's/^blob //p' \
| sort --numeric-sort --key=2 \
| cut -c 1-12,41- \
| $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest

执行上面命令记录太多,可能在控制台看不全,可以使用以下命令,输出到一个文件中(info.txt),方便查看

git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| sed -n 's/^blob //p' \
| sort --numeric-sort --key=2 \
| cut -c 1-12,41- \
| $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest > info.txt

方案三实战:用filter-branch去做git仓库的清理

移除commit中某个文件的引用

该命令仅仅只是移除commit中对某文件的引用,如果某次commit同时提交了要删除的文件和要保留的文件,该命令只会移除要删除文件的引用,并不会移除要保留的文件和当次commit记录,所以无需担心会把不该删除的文件删掉了。

  • 单独移除某个文件的引用
git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch 文件路径/文件名' --tag-name-filter cat -- --all

示例:

移除某个文件夹下所有文件的引用, 例如移除 node_modules/ 文件夹下面所有文件的引用

git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch node_modules/*.*' --tag-name-filter cat -- --all

删除指向旧提交的指针

rm -rf .git/refs/original/

让历史记录全部过期

设置所有未关联对象过期时间为现在,默认为90天。

目的是放弃所有未关联对象恢复的可能性,因为reflog 是找寻它们踪迹的最后途径了。

git reflog expire --expire=now --all

重新打包

执行完成后此命令后.git\objects\pack目录下会生成新的打包文件,垃圾文件会保留在pack的上层目录

git repack -A -d

对仓库进行 gc 操作

执行完成此命令后,会把刚才repack的垃圾文件进行删除,此时再看仓库大小已经明显被优化了。

git gc --aggressive --prune=now

强制推送到远程分支

git push --force

重新从远程仓库clone代码&检查项目大小

注意!注意!注意!

所有协作开发的小伙伴都要新建目录,重新clone代码,切勿使用原来本地的目录了+不要push,否则前功尽弃。

方案四:使用BFG工具优化

前置条件和注意事项:

1、把码云仓库自动发布停掉;

2、把仓库全权限收回,防止在操作过程中有小伙伴提交代码;

3、安装java环境;

4、下载bfg.jar工具包 ;

5、把下载好的bfg.jar放到项目目录上一层目录下;

实战项目: OA

先看下优化前大小:

  1. 拉取代码(仅拉取镜像) 提前下载好两个镜像

一个用来操作的:oa_management-mirror.git , 一个用来做安全备份:oa_management-mirror-copy.git

## 操作
git clone --mirror https://gitee.com/yz_rd_frontend/oa_management.git oa_management-mirror.git

## 用于备份
git clone --mirror https://gitee.com/yz_rd_frontend/oa_management.git oa_management-mirror-copy.git

  1. 备份库需要删除remot引用,断绝污染: git remote remove origin ;

cd oa_management-mirror-copy.git && git remote remove origin
cd ..
  1. bfg 推荐的优化(删除大于50M的文件)

java -jar bfg.jar --strip-blobs-bigger-than 50M oa_management-mirror.git 

  1. 删掉dist (不一定哈,通过扫描结果来觉得清理哪些文件)

java -jar bfg.jar --delete-folders {dist} --no-blob-protection oa_management-mirror .git 
  1. 清理完指定的对象后,需要对git的reflog记录进行清空, 并且进行git仓库的垃圾处理删除无意义的git对象

cd oa_management-mirror.git 
git reflog expire --expire=now --all && git gc --prune=now --aggressive

  1. 推送镜像

需要有推送权限(注意: 码云仓库设置: 功能设置->约束>强制推送, 把禁止强制推送关闭,操作完成后再开启)

git push --mirror
  1. 在本地新建一个文件(不要使用原来的项目文件夹),新拉取代码

get clone https://xxxxxxxxxxxx.git
  1. 检查下最新代码占用体积大小

git count-objects -v

优化后大小:40M

  1. 恢复码云自动发布webhook + 相关开发权限等配置

    备份镜像库可以之后再删除