Mark一下“清除A项目git仓库大文件”实操过程,由于公司保密政策,无法提供实操截图,这里提供下操作思路。

一、需求背景

  最初A项目的部署配置,是从远程仓库获取项目打包文件进行部署,这需要在本地生成打包文件后提交到远程仓库。

  而对打包大文件多次操作后导致git仓库过大(已达3G,正常为几十M),从而导致首次拉取项目速度过慢、同时也占用了大量存储空间。

  为了解决“项目过大导致首次拉取速度过慢、占用大量存储空间”问题,急需对git仓库进行清理–从git记录中清除不需要的大文件。

Git 仓库随着 commit 次数的增加变得越来越大,尤其是当 push 了大文件之后,即使后面把该文件删除了,也会被 Git 记录下来,以便能够随时回滚到指定提交。

二、技术方案

用 filter-branch 去做git仓库的清理

filter-branch:让您通过重写 <rev-list 选项 > 中中提到的分支来重写 Git 修订历史记录,并在每个修订版上应用自定义过滤器。这些过滤器可以修改每个树(例如,删除文件或对所有文件运行 perl 重写)或每个提交的信息。简单来说:filter-branch剔除指定的类型文件,并重写commitId。

1、注意事项(***)

!!清理完之后,每个人一定要删掉之前拉取的项目, 重新从git上拉项目。不要使用之前的项目了!否则会不降反升。

2、方案步骤
Step1:找占用空间大的文件是哪些;
git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
// 使用verify-pack命令查看, pack包里面的最大的10个文件对应的hash值
// 根据rev-list命令来查看, 最大的文件的文件名是什么
Step2:移除对该文件的引用;
git filter-branch --force --index-filter "git rm -rf --cached --ignore-unmatch 文件/文件夹" --prune-empty --tag-name-filter cat -- --all
Step3:重复第1,2,3三步, 继续查看是否还有资源需要清除;
Step4:回收空间,清理本地仓库不可达对象;
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
rm -rf .git/refs/original/
rm -rf .git/logs/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now
Step5:推送服务器,清除远程仓库;
git push origin --force --all 
git push origin –-force --tag
git remote prune origin 

// 项目会变小,后续拉取的项目也会变小,但是远程仓库由于缓存并不会变小
// git push origin --force --all 强制推送到远程所有分支,分支多的话,执行比较慢,可以只保留协作分支(master、dev),清除远程个人分支
Step6:推送服务器,清除远程仓库;
cd ${gitlab项目部署目录}/git-data/repositories/{待清理的项目地址}
git count-objects -vH // 此时还是旧的大小
git gc --prune=now  // 清理无效文件
git count-objects –vH // 此时就和本地一样,从库减小了

// 有权限可以尝试下这一步,不执行也不影响

三、执行计划

1、基于预瘦身项目远程仓库地址,fork一个备份项目

2、锁定git提交权限,清除远程开发分支

封锁git提交权限,避免在瘦身操作过程,有人提交记录,制造不必要冲突。
保留远程仓库协作分支(master/dev),清除其他开发分支 。(事先确保所有代码合并到dev分支中)

3、执行瘦身方案

在A项目采用上述方案进行瘦身,瘦身成功后并推着远程分支

4、重新拉取项目、开放git提交权限

项目开发者重新拉取项目并开放git提交权限

四、方案验证

目前方案已在A项目中验证成功,git仓库体积从3G减少至80M,克隆项目速度从1个小时缩小到1分钟。保险起见在执行项目瘦身操作前,需要基于A项目重新fork一个项目做备份。