0%

Git瘦身

简介

随着时间的推移,Git存储库变得越来越大。 将大文件添加到Git存储库后:

  • 个人电脑硬盘空间有限,仓库较多时,占用了大量存储空间。
  • 由于每个人都必须下载文件,因此获取代码库的速度变慢。
  • 它们占用服务器上的大量存储空间。
  • 会达到Git仓库的存储限制。
    重写存储库会删除不需要的历史记录,从而使存储库更小。 git filter-repo是用于快速重写Git存储库历史记录的工具。

注意:

重写存储库历史记录是一种破坏性操作。 
在开始之前,请确保备份您的存储库。 
备份存储库的最佳方法是导出项目。

1、准备工作

1、备份代码

仓库瘦身是一个复杂且危险的操作,可能导致代码丢失等问题,一定要做好备份,fork一份或在本地电脑拷贝一份,也方便瘦身后做比较

2、去掉分支保护

3、操作前通知所有人将手头代码提交到远程,且保证自己电脑里的代码是最新的,各个本地跟踪的分支都更新到最新

4、开始操作后,禁止大家提交代码

5、操作完通知大家重新clone

2、瘦身操作

1、瘦身前.git目录大小

瘦身主要是针对项目下面的.git目录操作,如当前.git目录所占大小为1.5G
此处输入图片的描述

2、查找大文件对象

这里封装一个脚本用来查找大文件对象,可以得到文件所占大小、所在目录等信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
#set -x
IFS=$'\n';

# 默认值是 10个 可以一次性展示更多 就修改第15行代码 | head -n 30 或者更多
objects=`git verify-pack -v objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head`

echo "All sizes are in MB. The pack column is the size of the object, compressed, inside the pack file."

output="size,pack,SHA,location"
for y in $objects
do
# extract the size in bytes
size=$((`echo $y | cut -f 5 -d ' '`/1024/1024))
# extract the compressed size in bytes
compressedSize=$((`echo $y | cut -f 6 -d ' '`/1024/1024))
# extract the SHA
sha=`echo $y | cut -f 1 -d ' '`
# find the objects location in the repository tree
other=`git rev-list --all --objects | grep $sha`
#lineBreak=`echo -e "\n"`
output="${output}\n${size},${compressedSize},${other}"
done

echo -e $output | column -t -s ', '

将该脚本放到该目录下,然后给 largelist.sh 文件赋予执行权限; 并执行文件

1
2
chmod +x largelist.sh
./largelist.sh

可以得到如下信息:
此处输入图片的描述

主要是大为小程序、RN引擎、地图库、语音识别库、RTC库等

3、大文件引用改造

早期项目对包含小程序、RN引擎、地图库、语音识别库、RTC库、pods依赖库都进行了代码管理,一部分业务库更是手动拖拽进来,随着开发成员越来越多,每次都会产生大量代码冲突,这里对项目进行了大刀阔斧的改造,具体:

  • 对pods依赖库去代码管理(业务组件化,RTC库、语音识别库、地图库等第三方库直接通过pod依赖)
  • 项目里的小程序引擎已经不再用了完全去掉
  • RN引擎、RN交互层改造成组件化的方式进行接入

4、重写所有commit:

1
2
3
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch Applet/Core/Libs/*.a" --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch Applet/Features/Libs/*.framework/*" --prune-empty --tag-name-filter cat -- --all
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
  • filter-branch: 是让git重写每一个分支;
  • –force 假如遇到冲突也让git强制执行;
  • –index-filter 选项指定重写的时候应该执行什么命令,要执行的命令紧跟在它的后面,在这里就是git rm –cached –ignore-unmatch /images/TestImagesForNSFW.rtf,让git删除掉缓存的文件,如果有匹配的话。
  • –prune-empty 选项告诉git,如果因为重写导致某些commit变成了空(比如修改的文件全部被删除),那么忽略掉这个commit。
  • –tag-name-filter 表示对每一个tag如何重命名,重命名的命令紧跟在后面,当前的tag名会从标注输入送给后面的命令,用cat就表示保持tag名不变。
    紧跟着的– 表示分割符,

最后的–all 表示对所有的文件都考虑在内。

5、回收内存

1
2
3
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

6、推送到远程

1
git push --mirror

3、效果

.git从1.5G降到了379MB
此处输入图片的描述

参考:

https://docs.gitlab.com/ee/user/project/repository/reducing_the_repo_size_using_git.html#repository-cleanup
https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#EXAMPLES