乐趣区

关于git:被吐槽-GitHub仓-库太大直接-600M-瘦身到-6M这下舒服了

大家好,我是小富~

前言

忙里偷闲学习了点技术写了点 demo 代码,打算提交到我那 2000Star 的 Github 仓库上,竟然发现有 5 个Issues,最近的一条日期曾经是 2022/8/ 1 了,以前我还真没注意过这些,我这人懒得很,本地代码提交胜利根本就不论了。

仓库地址:https://github.com/chengxy-nds/Springboot-Notebook

5 个 Issues 中,有个题目 ”优化本仓库大小的倡议“ 吸引我了,连忙点进去看看啥状况,这个哥们说我这个仓库太大了,仓库 700 多 M,半天也拉不下来,而后还给我附上了批改倡议(不要太贴心哦)。

我不信

开始我还有点不信,这仓库提交的是我平时写文章中跑的代码 demo,每个我的项目也就十来个文件几十 KB,怎么会有 700M 这么多,不信邪的我连忙看了下仓库大小Setting->Repositoriess,竟然真有 683M 这么多。

于是我连忙 Clone 仓库到本地,看看是不是我提交了什么大文件,下载过程的确挺折磨人,不仅慢还常常中断,在通过不晓得多少次重试之后,终于下载下来了。

翻了翻各个我的项目发现里边确实有许多应该疏忽的文件 .idea.mvntarget 都被我提交了,间接删除文件,但并没有什么卵用,我的项目整体 size 变动不大,应该不是这些文件的起因。

我用 du 命令看了下各目录的文件大小,发现 ./springboot-seata-transaction 目录 45M,因为里边有一个 jar 间接删除就行了;而 .git 足足有 688M,看来问题就出在这个目录,重点优化下。

这目录好大

那么 .git 目录是寄存什么的?为什么会这么大呢?

Git 零碎中,.git 目录中存储了整个代码仓库的元数据信息(包含提交历史记录、分支、标签等)和文件对象。

我在该目录上用 du 命令看了一下,发现 objects 目录竟然有 683M,那么问题就是出在它身上了。

objects目录之所以这么大,是因为它保留了仓库中的所有历史版本和数据对象,也就是 blobs 文件内容, trees目录构造, commits提交历史,它们是 Git 中的三个外围对象类型。

其中:

  • Blobs: 每一个文件都被视为一个二进制对象(Blob 对象),它保留了文件的所有内容和一些元数据信息,如文件名、文件类型、文件大小等。当文件发生变化时,Git 会主动计算并存储新的 Blob 对象,并将其与先前的 Blob 对象做比拟,以确定文件的变动状况。
  • Trees: 目录也被视为一个对象(Tree 对象),它保留了目录中蕴含的所有文件和子目录的列表,每个列表项包含了文件或目录的名称、类型、权限等信息,以及对应文件或目录的 Blob 或 Tree 对象的 SHA 校验和。
  • Commits: 咱们每次提交代码,就会产生一次 Commit,Commit 对象保留了一次代码变更的相干信息,包含作者、提交工夫、父提交记录的 SHA 值、形容信息等。每个 Commit 对象还蕴含指向对应代码快照的 Tree 对象的 SHA 校验和。

上边三种类型的对象组成了 Git 中的根本数据单元,通过这些对象的组合和链接,才构建出残缺的提交历史,并跟踪代码库中每个文件的变动历史。这个目录是 Git 中最重要的目录之一,所以对它操作要审慎,不然很容易失落历史记录。

瘦身利器

只管咱们晓得了大文件的地位,可具体该删除哪些文件无从下手啊,objects目录下都是些压缩文件,弄不好整个仓库都得报废。

好在提 Issues 的兄弟还给举荐了个 Git 仓库瘦身的工具,该说不说真的贴心啊。

这个 Git 仓库清理工具叫BFG Repo-Cleaner,能够帮忙咱们筛选、清理大文件对象,官网文档地址:https://rtyley.github.io/bfg-repo-cleaner,接下来看看这工具咋用。

留神 :在做以下操作之前, 肯定要备份!!! 肯定要备份!!! 肯定要备份!!!

1、下载安装

BFG 是以 java -jar 的形式启动,首先装置不低于 JDK8+ 的环境,并下载 BFG 的Jar 包。

$ wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar

2、clone 仓库

在 clone 仓库的时候举荐应用 --mirror 参数,将源仓库的所有分支、标签以及提交历史都残缺地克隆到本地,只会拉取 .git 目录的相干文件。

$ git clone --mirror git://example.com/Springboot-Notebook.git

3、查找大文件

bfg-1.14.0.jarSpringboot-Notebook.git 放在同一级目录下,执行下边的命令过滤出大于 20M 的文件对象。

# 查找出大于 20M 的须要清理的文件
$ java -jar bfg-1.14.0.jar --strip-blobs-bigger-than 20M Springboot-Notebook.git

看到过滤出了很多大文件,蕴含了 Issues 中兄弟提到的那个 Jar 包。

4、删除大文件

应用 --delete-files 命令逐个的将大文件删除,如果提醒分支是被爱护的能够加上 --no-blob-protection 命令执行。

# 查找出大于 20M 的须要清理的文件
$ java -jar bfg.jar --delete-files Cyrillic.traineddata  Springboot-Notebook.git 

5、GC 回收垃圾

上边咱们尽管过滤、删除了大文件,此时仓库的大小依然没有变动,进入 Springboot-Notebook.git 仓库内,执行 git reflog expiregit gc命令,压缩 Git 库中的历史版本、革除废除的、过期的对象,这个过程会消耗较长的工夫。

# 进入目录
$ cd Springboot-Notebook.git

# 执行 git gc 回收垃圾
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive

# 推送
$ git push

最初推送代码到近程仓库,在看仓库的大小曾经降到了 108M,成果挺显著,剩下的 108M 应该就是我频繁提交导致的了,查了下我竟然有 127 次提交之多。

每次提交都会生成一次快照,这些快照可能蕴含大量的文件和代码,频繁提交会导致版本库中快照的数量减少。Git 应用的是一种增量存储形式,每次提交只存储产生了变动的文件和代码。

然而,如果频繁提交的变动较小,比方只是批改了几个字符或者行末空格,Git 可能无奈正确地检测出这些变动,而将整个文件都存储起来,也会减少了.git 文件的大小。

彻底一点

起初我想了想这个仓库存在的意义,不就是让大家看着文章跑 demo 代码嘛,能 疾速的下载并胜利运行 才是他们在乎的,谁又会在意提交记录。那我罗唆彻底一点,清理掉仓库的所有提交记录,一劳永逸。

那么操作起来就得小心一点了,毕竟 2000star,别把仓库弄嘎了,既要革除一个分支上的所有提交记录,同时又不能删除这个分支自身,其实咱们能够曲折一下。

咱们首先应用 --orphan 命令创立一个全新的分支new-branch,这个新建的分支和其余分支没有任何关系,它不会蕴含任何先前的提交记录或者历史记录。相当于新建了一个洁净的空分支,并让该分支指向一个全新的根节点。

git checkout --orphan <new-branch-name>

而后 commit 全副的我的项目文件到这个分支,暂不须要推到近程仓库。

git add -A
git commit -am "Initial commit"

接着删除旧的分支,并把新建的分支名改成旧分支名称,推到近程仓库就行了。

# 

git branch -D <old-branch-name>
git branch -m <old-branch-name>
git push -f origin <old-branch-name>

在推完代码后我再次去看了下仓库的大小,当初就只有 6.33M 了,如果不是人脸识别我的项目中有几个必要的 SDK 包,应该还能在小点。

总结

以我本人的亲身经历做为反面教材,揭示大家操作 Git 要审慎,工作中严禁提交该疏忽的文件;提交代码要管制节奏,不能得心应手,尤其是团队合作开发;如果发现 .git 文件太大,举荐应用 Git LFS 来治理大文件,千万不要像我这么操作,毕竟随便删除提交历史记录,在哪个公司都是不合规的。

重点感激下提出倡议的大兄弟

退出移动版