赞
踩
说到代码版本管理,现在首屈一指的就是Git。感谢Linus教主于15年的创举,从此码农世界就改变了。Git千好万好,就有一点不好,那就是对大型二进制文件不友好。对于一个有许多大型二进制文件的项目,比如视频游戏仓库,对仓库的管理和处理就非常头疼。由于Git底层设计逻辑,每一次版本变化时候都是做全文件快照,如果如果一个大的二进制文件(比如视频)有多次变化,那么Git仓库的大小将会是倍数级的增长,这样在仓库同步、团队协作时候,尤其是成员初始Clone时候将一个噩梦。
当然针对这个问题Git开源社区也一直在想办法解决,比如一个解决问题(不是根本)的办法Git LFS。
还有一个比较优雅的办法就是使用部分克隆(Partial Clone)
部分克隆Git的一项新功能,它用来取代了Git LFS,并通过控制Git下载(或者跳过)部分Git仓库对象(快照)的方法从根本来是实现对大文件的管理。关于部分克隆虫虫以前的文章介绍过,本文我们来深入介绍Git部分克隆。
部分克隆的发展受到业界的关注和参与包括Git翘楚GitHub和GitLab,以及IT巨头微软和谷歌。GitLab从12.4开始beta版本支持。
部分克隆可以大大加快获取和克隆的速度,由于减少了Git对象的下载,可以节省网络传输,也可以大大节约本地用户的磁盘空间。
和部分克隆相伴随着的还有一种选择性下载方法,那就是稀疏签出(Sparse Checkout),稀疏签适合具有大量文件和版本的仓库 。
Git大文件仓库的历史要追溯到2010年的git-annex。git-annex 采用 Haskell Script 编写,允许映射Git资料库到文件,帮助用户管理Git仓库的文件,git-annex的设计中大文件是独立于Git仓库中保存的,在git仓库中只保存文件名和文件元数据等信息用来实现大文件追踪。
git-media 是使用 Ruby 语言开发的,和git-annex把大文件(media)存储在本地定期同步的方法不同。 git-meida一个中心服务器来存储大文件的方案。用于通过git media sync命令进行同步
2015年,Git社区发布了自带的解决方案Git LFS(Large File Storage),该方案类似于git-media。
Git LFS方案中可以把音乐、图片、视频等指定的大文件存在 Git 仓库之外存储,在 Git 仓库中用一个元数据文件来代替(.gitattributes)。通过把大文件存储在 Git 仓库之外,可以减小 Git 仓库本身的体积,使克隆 Git仓库的速度加快,也使得 Git 不会因为仓库中充满大文件而损失性能。
目前Git LFS 已经被主流的Git服务商支持,GitHub 和 GitLab 都对其提供内置支持。
但是这些解决方案中,都是通过把大文件置于Git仓库之外存储的针对问题的临时解决方案而不是根本的解决方法。方案中要单独维护大文件管理,对其同步和下载管理都比较繁琐,而且其对应存储在git仓库中的额外的元属性文件也会干扰Git仓库管理。
针对这些问题,部分克隆可以避免维护两种存储和元属性文件的管理的问题,从而从根本上优雅的解决大文件的问题。
我们以Gitlab gitlab-com/www-gitlab-com 为例子介绍。该项目是gitlab在线文档仓库,仓库中有很多图像,3.5G的文件。使用部分克隆(--filter=blob:none)进行部分克隆至少可以加快要50%,下载的数据可以减少70%。
对于更仓库库,比如具有详细纹理和模型的视频游戏仓库,部分克隆的性能提高将更加明显。
和传统的git clone相比较,部分克隆提供一个过滤器规范,该规范可控制下载Git对象时要排除的内容。比如,本例中,我们想要排除大型二进制文件。我们使用--no-checkout对比显示效果。
上面我们通过--no-checkout选项,制定Git不签出默认分支。通常情况下checkout不需要从服务器获取任何数据,因为在clone本地已经下载了所有对象。上面使用部分克隆时,由于故意设置没有下载所有内容,因此Git在后续checkout操作时候需要获取所有本地不存在的对象。
我们继续签出其他分支或提交时,则需要下载更多不存在的快照对象。
Git可以记得在克隆仓库时提供的过滤器规范,以便获取更新还可以排除大型文件,只会在需要这些文件,才会下载对应的快照对象。
git config remote.origin.promisor
# true
git config remote.origin.partialclonefilter
# blob:none
提交更改时,只需和其文件一样提交二进制文件。无需安装或配置额外的工具,无需将大文件与小文件区别对待。
Git LFS的缺点之一是它需要安装其他工具。而部分克隆不需要任何其他工具。只需更新git版本,并学习git已有命令的一些新的选项。比如git clone的--filter选项。需要自己确定过滤器最佳的Blob大小或其他过滤器的参数。
如果使用过LFS的同学可能知道大文件的存储和传输方式与常规Git对象是不一样的,他们都是额外存储的。由于要兼顾大存储,所以最终的存储媒介和一般文件不一样(SSD),所以下载要慢一点。而部分存储则是完全存在Git对象中,可以完全享受Git快速存储的优势。以Gitlab的部分存储为例,他们可以支持多区域服务器,可以根据自己的位置选择离自己较近位置的区域服务,这样可以实现更好的下载性能。
当使用过滤器规范从Git服务器排除部分对象的下载时,Git会检查每个对象并排除任何与过滤规范匹配的对象。Git最新版本2.25中,尚未针对性能优化过滤性能优势不明显。但是Git开源社区也在促进这部分优化完善,Jeff King提交提交了一个部分克隆Blob大小过滤的性能改进补丁,该补丁可以极大提高性能,预计会在Git 2.26中发布。服务器侧GitLab预计在4月22的12.10版本中会引入。
对--filter:sparse基于文件路径进行过滤的稀疏过滤器的优化则更复杂,由于包含文件内容的Blob不包含文件路径信息,存储库的目录结构存储在树对象中。
对大仓库的管理,还有一个需要考虑的问题就是对客户端用户文件锁定和工具集成的。和纯文本源代码不同,解决二进制文件不同版本之间的冲突通常是不可能的。为了防止二进制文件编辑中的冲突,一般会使用排他文件锁定,这意味着一次只能由一个人编辑文件,而与分支无关。如果无法解决冲突,则允许在不同分支上并行创建文件的多个版本会报错。Git服务器端已经具有基本的文件锁定支持,但只对对纯文本有用,也仅适用于默认分支,并且还不能与任何本地工具集成。
本地工具集成对于二进制文件工作流,自动将文件锁传播到本地开发环境以及允许设计人员无需在命令行上使用Git的需求非常重要。将文件锁快速传播到本地开发环境也很重要,因为它可以防止在工作发生之前就浪费工作。
大文件对于许多项目来说是必需的。尽管部分克隆还是一种实验性功能,但是其基于git根本解决方案,具有天然的优势,开源社区也对该功能进行不断地优化和完善。一个功能成熟、高性能的Git大文件优雅管理的解决方案预计很快就有了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。