文档结构  
翻译进度:已翻译     翻译赏金:1 元 (?)    ¥ 我要打赏

git是跟踪记录代码变化和协同合作的极好的选择。但是当你要跟踪的存储库极大时怎么处理呢?

在这篇文章中,我会给你一些建议来适当地处理不同类型的大型存储库。

两种大型存储库

如果你仔细思考一下,存储库规模增长的原因主要有两个:

  • 经历了较长时间的积累 (项目历时很长,存储的东西不断积累)
  • 它包括需要跟踪和并代码配对的大规模二进制代码。
  • 以上两个。
第 1 段(可获 1.43 积分)

因此一个存储库可以往两个垂直的方向增长:工作目录的大小, 即最新提交的内容 — 以及整个历史阶段存储的东西。

有时。第二类问题伴随着的是,被弃用的二进制产品仍存储在库中。但是如果你为此烦恼,想要解决这个问题,有一个简单的办法请看下文。

上述两个场景的技术和解决方案是不同的,尽管有时互补, 我们仍将它们分离开。

处理历史悠久的仓库

第 2 段(可获 1.11 积分)

尽管定义一个存储库为海量存储库的方法很广 - 例如,最新的Linux内核的代码是150万行, 但是人们似乎乐于看到全部代码 - 因为法律/监管的原因,一些旧的项目必须保持完整,这使它们变成差劲的复制品 (为了透明化,linux内核被分为历史库和最新的库, 并且需要一个简单嫁接设置使我们能够访问完统一的历史).

浅克隆是一个简单的解决方案

为了快速克隆,节省开发人员、系统开发时间以及磁盘空间,第一个解决方案就是通过git进行浅克隆。浅克隆能让你只克隆一个储存库最新几次提交的版本。

第 3 段(可获 1.66 积分)

我们如何能做到? 只需使用- -depth 选项, 如:

git clone --depth depth remote-url

想象一下,你的库积累了十年或十年以上的项目历史记录——如,JIRA 是一个迁移到 git 有 11 年之久的老库,将节省的时间加起来就十分显著了。

完全克隆 JIRA 需要 677MB,包含工作目录的话,还需要额外的 320+MB,总计需要 47000+ 次提交。用浅克隆的方式检查 JIRA 需要 29.5 秒,而检查完整的历史记录需要 4 分 24 秒。随着时间的推移,项目二进制会增长,相应地,这个差距也会随之增长。在任何情况下,构建系统都能从这种技术中受益。

第 4 段(可获 1.55 积分)

近期 Git 已改进对浅克隆的支持

浅克隆在某些操作中并未得到支持,就像 git 世界的残疾人一样。但最近更新的版本(1.9+)已很好地改善了这种情况,你可以使用浅克隆简单地对库进行 pull 和 push 操作。

另一个解决方法是 Filter-branch

大型库往往会出现因错误提交的二进制问题,以及多余的资源,解决此类的问题的一个有效方法就是使用 filter-branch。这个命令允许浏览项目的全部历史记录,然后根据预先定义的模式进行过滤,整理,修改,文件跳过的处理。它是 git 工具集中一个十分强大的工具。目前已有协助脚本帮助识别 git 中的大对象,因此,现在操作起来简单许多。

第 5 段(可获 1.59 积分)

filter-branch 的示例用法:

git filter-branch --tree-filter 'rm -rf /path/to/spurious/asset/folder' HEAD

filter-branch有一个小小的缺点:一旦你使用filter-branch,你可以有效地重写项目的整个历史记录。所有提交ID都会更改。 这要求每个开发人员重新克隆更新的存储库。

因此,如果您打算使用filter-branch执行清理操作,则应该提醒您的团队,在执行操作时计划一次冻结,然后通知所有人应该再次克隆存储库。

第 6 段(可获 0.89 积分)

浅克隆(Shallow-Clone)的替代方法:只克隆一个分支

自从git 1.7.10(2012年4月)以来,您还可以通过克隆单个分支来限制您克隆的历史记录数量,如下所示:

git clone URL --branch branch_name --single-branch [folder]

这个特殊的用法对于长时间运行和分叉的分支,或者当你有很多分支时是有用的。 如果你只有少数几个差异很小的分支,你可能看不到使用浅克隆带来的巨大差异。

Stack Overflow参考。

处理巨大的二进制资产的存储库

第二类大型存储库由代码库组成,这些代码库必须跟踪巨大的二进制资产。 游戏团队必须围绕巨大的3D模型进行整合,Web开发团队可能需要跟踪原始图像资产,CAD团队可能需要操纵和跟踪二进制可交付成果的状态。 所以各种不同类别的软件团队在使用git时遇到了这个问题。

第 7 段(可获 1.79 积分)

Git在处理二进制资产方面并不是特别糟糕,但也不是特别好。 默认情况下,git将压缩并存储所有后续的完整版本的二进制资源,如果你有很多版本时,这显然不是最好的。

有一些基本的调整可以改善这种情况,比如运行垃圾收集git gc,或者在 .gitattributes中调整某些二进制类型的delta提交的使用。

但是,重要的是要反思项目的二进制资产的性质,因为获胜方式可能会因此不同。 例如,这里可以检查以下三点(感谢Stefan Saasen的评论):

第 8 段(可获 1.25 积分)
  • 对于显著变化的二进制文件 - 而不仅仅是一些元数据头 - 增量压缩可能是无用的,所以建议将这些文件的delta关闭,以避免重新打包时不必要的delta压缩工作。
  • 在上面的情况下,这些文件很可能也不会被很好压缩,于是你可以使用core.compression 0或core.loosecompression 0将压缩关闭。这是一个全局设置,会对所有实际压缩的很好的非二进制文件产生负面影响,因此如果将二进制资源分割在单独的存储库中,这样的建议是有意义的。
  • 重要的是要记住,git gc将“重复的”松散对象转换为单个包文件,但是除非文件以任何方式压缩,否则这些对象与生成的包文件的相关性不会有任何显著差异。
  • 探索core.bigFileThreshold的调优。任何大于512 MiB的内容都不会被压缩,而不必设置.gitattributes - 所以也许这是值得调整的东西。
第 9 段(可获 2.1 积分)

技巧1:稀疏检出(Sparse Checkout)

对二进制资产问题的轻微帮助是稀疏检出(从Git 1.7.0开始可用)。 这种技术允许我们通过明确详细说明要填充的文件夹来保持工作目录的清洁。 不幸的是,它不会影响整个本地存储库的大小,但如果您有一个巨大的文件夹树时,可能会有所帮助。

涉及的命令是什么? 这是一个例子(credit):

  • 克隆一次完整的存储库:git clone <repository-address>
  • 激活功能:git config core.sparsecheckout true
  • 添加显式需要的文件夹,忽略资产文件夹:
第 10 段(可获 1.1 积分)
echo src/ › .git/info/sparse-checkout
  • 读取指定的树: git read-tree -m -u HEAD

完成上述指令之后,您可以继续使用常规的git命令,但是您的工作目录将仅包含您上面指定的文件夹。

技巧2:使用子模块

处理巨大的二进制资产文件夹的另一种方法是将它们分割成一个独立的存储库,并使用子模块拉取主项目中的资产。 这为您提供了一种控制何时更新资产的方法。 在这些帖子中查看更多关于子模块的内容:核心概念及提示替代方案

如果您使用子模块的方式,您可能想要检查处理项目依赖关系的复杂性,因为我提到的方法可能会有助于巨大二进制文件问题的一些可能的解决办法。

第 11 段(可获 1.58 积分)

技巧3:使用Git Annex或Git-Bigfiles

使用git处理二进制资产的第三个选项是依赖于适当的第三方扩展。

我提到的第一个是git-annex,它允许使用git管理二进制文件,而不会将文件内容检入存储库。 git-annex将文件保存在特殊的键值存储中,只有符号链接被检入git并且像普通文件一样被版本化。 它使用起来非常简单而且这些例子都是明白易懂的

第二个是git-bigfiles,这是一个git fork,希望能让那些在项目中使用git管理大文件的人感觉可以承受。

第 12 段(可获 1.26 积分)

结论

不要因为您拥有巨大的存储库历史或巨大的资产,而放弃git的奇妙功能。 这两个问题都有可行的解决方案。

跟随我@durdn和令人敬畏的@AtlDevtools团队与更多的DVCS(译注:分布式版本控制系统)一起摇摆吧。

第 13 段(可获 0.49 积分)

文章评论