开发者学堂课程【Git 从入门到进阶:Git 的十年变化(九)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1194/detail/18123
Git 的十年变化(九)
内容介绍:
一、前期内容复习
二、git 仓库膨胀的两种常见原因
三、git 仓库膨胀的解决方法
四、普通克隆、LFS、部分克隆、浅克隆的对比
五、拓展
一、前期内容复习
第二期,学习了 Git 背后的各种现象,其中包括 blob 对象存储了文件的实际内容。另外,commit 时还会生成相应的 commit 对象和 tree 对象,第四期,通过小明撰书的例子,了解了松散对象存储的细节。松散对象保存了文件的实际内容,并且通过 git gc命令。git 会通过 delta 的方式压缩生产对象。理解这些内容会对下面的学习有帮助,如果大家觉得这些内容有些陌生,可以点击链接复习。
二、关于Git仓库越来越大的问题存在两种原因
1.向仓库中提交了二进制文件。常见的二进制文件有音频、图片、编译后的程序等等,由于超过一定体积的文件。(core.bigfilethreshhold 控制)git 不会对其进行压缩。即便体积没有达到这个阈值,对二进制文件进行压缩,压缩率也并不高,仓库体积会很快膨胀。
2.随着时间的积累,git 会保存仓库中每一个文件的每一个历史版本,仓库也同样会越来越大。
三、解决仓库膨胀的方法
1.使用GIT LFS。
GIT FLS 是 Git 的一个插件,需要单独安装 https://git-lfs.github.com/ 执行git lfs track 即可将对应文件纳入lfs管理。例如:git lfs track ”*.bin”
这适用于向仓库中添加了大体积的二进制文件的情况。二进制文件会被转为摘要文件(120字节左右),存在于 Git 仓库中。实际文件,存于第三方的存储中。摘要文件告诉Git,如何找到实际文件。克隆仓库时,当前检出分支的摘要文件会被替换为真实文件。历史的二进制文件,仅以摘要形式存在。
例:在这个工程当中,总共有三个提交,工程下有三个目录 backend frontend 以及build,分别用于存放后端相关的代码、前段相关代码以及一些中间编译产物等。Backend 下有3个文件、frontend 下有2个文件、build 下有4个文件,假设每次提交都修改所有文件,因此每个文件都会有3个版本。
在仅使用 git clone 来克隆仓库的情况下,会完整的下载仓库新的所有文件的所有版本,并且二进制文件的体积大于文本文件的体积,因此会消耗大量的时间在下载历史版本上。
使用 GIT FLS 后仓库的结构:
对于当前检出的分支来说,工程目录下所有文件都会被下载。对于历史的提交来说,二进制文件以摘要形式存在,与使用普通克隆的仓库来说,有八个二进制文件的历史版本,以摘要形式存储,假如每个二进制文件的大小为500MB,相比于使用普通的克隆,就节省了4gb 的空间以及对应的时间。
此外,如果仅关心源码的情况下,可以不安装 git lfs 程序。这种情况下,当前分支的四个二进制文件也会以摘要形式存在,更进一步的节省了时间及空间。
Git lfs 通过将历史的二进制文件。替换为摘要存储。优化了二进制文件的存储,但是观察上图可以得出。存储文件的历史版本依旧被下载,当文件被修改的次数比较多时。这些文件的历史版本同样也会占用大量体积,那么就可以用一种新的办法将历史版本过滤掉,即 Git v2协议的扩展。
2.部分克隆
Git protocol v2协议,扩展了服务器与客户端的交互能力。
要使用Git的v2协议,需要本地git客户端的版本在2.22.0以上。
Protocol v2中服务器可以向客户端广播 filter 特性。
客户端可以通过 fliter 选项告知服务器其希望过滤的对象。
开启 partial clone 需要在客户端及服务器都支持v2协议的情况下,使用 partial clone:git clone--filter=<filter-spec>
各个代码平台对 filter 的支持不同。阿里云的 codeup 上支持的 filter 有:filter=blob:none(用于过滤仓库中的blob文件)和filter=tree:<depth>(可以按照目录的深度来进行过滤)
3.浅客隆
blob:none 模式的克隆仅会下载 commit 以及 tree 对象,由于克隆后的checkout,当前检出分支下的文件也被下载下来。相比于 lfs 的克隆,历史提交中的 blob 的的对象并没有被下载,后续在用到历史版本文件时,git 也后自动为我们下载,部分克隆会保留仓库完整的历史提交信息,若想省略提交信息,可以使用 git 浅克隆,通过--depth<depth>来使用浅客隆,当仓库内含有大量的提交历史时,使用浅克隆带来的速度提升可能会非常可观。例如完整克隆 linux 仓库需要下载约800万个对象,而使用深度为1的浅克隆。仅需下载约8万个左右对象。
注意:由于仅下载了部分的提交,此时运行 get long 命令,将无法看到仓库的历史提交以及历史改动。浅克隆更适合构建的场景,仅下载最新一个版本的代码进行构建,而并不十分适合日常的开发工作。
四、普通克隆、LFS、部分克隆、浅克隆的对比
1.普通克隆,通过 git clone 开启,会下载文件的所有版本,克隆后本地存有仓库的完整历史,最为熟知常用。
2.LFS,需要单独安装LFS程序开启,历史二进制文件与摘要形式存在,在检出提交时摘要文件会替换为实际文件,适用于仓库中有二进制文件的情况。
3.部分克隆,以--filter 开启在保留仓库完整历史的情况下,按照给定的 Filter 过仓库中的 Blob 或者 tree 对象,在执行一些 git 命令需要需要用到文件的内容时,git 会自动为我们下载缺失文件。
4.浅克隆,以--depth 开启,仅下载给定深度的文件,在构建等场景下,并不需要仓库的提交,只关心当前最新版本的代码。这种方式并不适合日常开发工作。
五、拓展
假如不关心后端的代码记以及编译的产物,可以使用部分克隆配合稀疏检出特性,在过滤仓库文件历史版本同时只下载 fontend 文件夹的文件。
例如想要学习 linux 仓库的内核部分即 kernel 下的代码,可以先使用部分克隆配合no-checkout 选项仅下载仓库的提交信息,配置稀疏检出为。
只检出 kernel 下的文件,最后执行 git chekcout 命令,这种方式下只需下载542.85 mb 的数据,而完整下载仓库则需 3.41 gb 数据。

