首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Git新版本2.42,新功能亮点尝鲜

近期最流行的版本管理软件Git软件发布了最新的一个版本,那么最新版本带来了什么样新功能呢,请大家和虫虫一起来学习尝鲜一下。

快速对象遍历方法

Git中曾在2.34版本(2021年底)中引入了新多包可达性位图。可达性位图允许Git快速确定可达性查询的结果集,例如在提供提取或克隆服务时。集合图Git存储少量提交的位。每个位位置都与一个特定的对象相关联,这个位的值指示它是否可以从给定的提交到达。

使用位图可以实现更快地计算可达性查询的答案,尤其是在于大型存储库的项目中。例如,如果想知道某个分支相对于另一个分支唯一的对象集,可以为每个端点构建一个位图,并计算两者AND NOT。 对于可达性查询一侧唯一的一组对象,生成的位图的位设置为“1”。

但是,如果一侧没有位图覆盖,或者分支自上次被位图覆盖以来已继续移动,会发生什么情况?

在老版本的Git中, Git将为与查询相关的所有可达性提示构建完整的位图。它通过从每个尖端向后行走,组装自己的位图,然后在历史中找到现有位图时立即停止。

遍历例程的流程示例:

上面有一个提交图,有五个分支和一个标签。 每个提交都由圆圈来表示,引用由指向其各自引用对象的方块表示。可以找到现有的位图v2.42.0标签和分支 bar。

在上面,尝试计算可从以下位置访问的对象集main,但无法从任何其他分支访问。经检查,答案显然是,Git遍历的步骤:

于想要从结果集中排除的每个分支(foo, bar, baz, 和quux),沿着提交图回溯,标记我们的每个相应的位位图位于左上角。

如果碰巧遇到了已经涵盖的图表的一部分,可提前停止。同样,如果一个现有的位图(bar),可以OR在该提交的位图中的位设置完毕,然后前往下一个分支。

然后,对想要保留的每个分支重复相同的过程(main),这次标记或 OR位入的位图。

最后,一旦有了代表可达性查询每一侧的完整位图,就可以通过以下方式计算结果AND NOT将两个位图组合在一起,留下一组唯一的对象main。

可以在上面看到,具有现有的位图覆盖(与分支的情况一样)非常有用,因为它们允许立即发现从图中的某个点可到达的对象集,而无需逐一和解析对象。

但是当位图覆盖稀疏时会发生什么? 在这种情况下,最终还得不遍历许多对象才能找到现有的位图。通常,维护一系列位图的额外开销超过了使用其的好处,特别是在覆盖范围很差的情况下。

在新版本中,Git引入了位图遍历算法的新变体,该算法的性能通常优于现有实现,特别是当位图覆盖稀疏时。

新算法将可达性查询的不需要的一侧表示为来自查询边界的位图,而不是来自不需要的一侧的各个提示的位图的并集。查询边界的确切定义有点技术性,目的,可以将其视为所需对象集中的第一个提交,该对象也可以从至少一个不需要的对象访问。

在上面的例子中,这是提交C₅,两者均可到达main(这是可达性查询的想要的一半)以及bar和baz(两者都在不需要的一半中)。让使用基于边界的方法逐步计算相同的结果:

做法与上面类似,但又不完全相同。步骤如下:

首先发现边界提交,在本例中C₅。

然后,从刚刚发现的边界提交集向后走,直到找到可达性位图(或到达历史的开头)。 在步行的每个阶段,所处的位图。

然后,在上面建立一个完整的位图需要的一侧开始步行main直到命中现有位图、历史记录的开始或上一步中标记的对象。

最后,和此前一样,计算AND NOT在两个位图之间进行比较,并返回结果。

当位图靠近边界提交时,或者查询中不需要的一半很大时,该算法通常远远优于现有的遍历。在上面示例中,可以看到使用基于边界的方法时我们可以更快地计算答案。

通过实际基准测试,两种算法存在2到15倍的性能差异。

也就说通过新版版本改善可以提高2~15的性能改善。

要尝试运行新算法,可以在新版本中通过命令来启用:

在存储库中,使用git rev-list与 --use-bitmap-index标志配置。

按模式排除引用

写过Git脚本的同学可能都熟悉其熟悉它for-each-ref命令(不知道也没关系)。可以用该命令枚举存储库中的引用:

for-each-ref对于列出引用、查找哪些引用指向给定对象(使用--points-at),引用已合并到给定分支(带有--merged),或者引用包含给定的提交(带有 --contains)。

Git通过与for-each-ref跨越许多不同的组件,包括推送的参考信息阶段。在推送期间,Git服务器首先公布它希望客户端了解的引用列表,然后客户端可以从推送期间生成的包文件中排除这些对象(以及可从它们访问的任何内容)。

Git 实现了配置的功能 transfer.hideRefs通过枚举所有引用,然后检查每个引用以查看是否应该向推送者通告该引用。一个示例:

在这里,要列出所有不以refs/pull/。为此,Git逐一枚举每个引用,并执行前缀比较以确定是否将其包含在集合中。

对于具有少量隐藏引用的存储库来说,这并不是什么大问题。但是,如果有数千个、数万个甚至更多隐藏引用怎么办? 执行如此多次前缀比较只是为了将引用丢弃为隐藏,成本就会非常高。

在Git 2.42中,新引入了一种新机制可以更有效地排除引用。Git再去逐一检查每个引用,而是首先在其所在区域中定位每个排除区域的开始和结束位置。 packed-refs file。一旦有了这些信息,它就会创建一个跳转列表,允许它一步跳过排除引用的整个区域,而不是一一丢弃它们,如下所示:

就像前面的例子一样,仍然想丢弃所有的refs/pull结果集中的引用。为此,Git会找到第一个以refs/pull(如果存在),然后执行二分搜索以查找所有以开头的引用之后的第一个引用的位置refs/pull。

然后,它可以使用该信息(由黄色虚线箭头表示)来避免查看refs/pull完全层次结构,与单独检查和丢弃每个隐藏引用相比,提供了可测量的加速。

在Git 2.42 中,通过git for-each-ref的新--exclude选项。新版本还使用新机制来改进上面的参考广告以及用于获取的类似组件。在极端示例中,这可以将推送期间广告引用的 CPU 成本提高20倍。

for-each-ref的 --format选项以及一些格式化参考的新方法。

第一组新选项使 for-each-ref在参考提示中显示一些有关提交的 GPG 相关信息。 可以直接请求GPG签名,也可以请求其各个组成部分,例如其等级、签名者、密钥、指纹等。比如,

2.42还附带了两个新选项git pack-refs命令,负责更新packed-refs包含任何未存储的新松散引用的文件。 某些情况下(例如频繁更新或删除的引用),将这些引用排除在外可能会很有用。packed-refs文件放在第一位。

git pack-refs现在了解如何使用其新功能来调整它所打包的参数--include和 –exclude选项。

防止GC回收

Git中有一种GC无法访问对象的新机制,称为cruft packs 。Git使用cruft pack 来收集和跟踪存储库中无法访问的对象的年龄,逐渐让它们老化,然后最终从存储库中删除。

但Git不会简单地删除每个无法访问的对象(除非使用--prune=now选项)。其GC回收的规则为:

如果对象是可访问的,在这种情况下GC永远不会删除它。

如果对象无法访问,但在修剪截止后已被修改。

如果对象无法访问,并且自修剪截止以来尚未被修改,但可以通过最近修改的其他一些无法访问的对象访问。

但是有特殊的需求想保留一个无法访问且自剪枝截止以来尚未修改的对象(或多个对象),怎么实现?

从历史上看,这个问题的唯一可行方案是应该将引用指向这些对象。如果想要保留一组相对较小的对象,那么这种方法就有效。但是,如果想要保留的对象超出了过所能跟踪的范围,该怎么办?

Git 2.42引入了一种新机制来保留无法访问的对象,无论它们最近是否被修改过。使用新的gc.recentObjectsHook配置中,可以配置Git在即将执行修剪垃圾收集时运行的外部程序。每个配置的程序都可以打印出以行分隔的对象ID序列,每个对象 D都不受修剪的影响,无论其年龄如何。

即使之前从未使用过cruft packs,即使使用松散对象来保存尚未从存储库中过期的无法访问的对象,这个新的配置选项也可以工作。

这使得可以使用外部机制(例如SQLite数据库)来存储大量潜在的无法访问的对象,希望将这些对象无限期地保留在存储库中:

稀疏索引

随着时间的推移,许多命令都获得了使用稀疏索引的支持。对于缺乏稀疏索引支持的命令,调用这些命令将导致存储库扩展索引以覆盖整个存储库,这可能是一项潜在昂贵的操作。

新版本中, diff-tree命令加入了完全支持稀疏索引的命令组,现在可以使用 diff-tree无需扩展索引。

本文只列举了部分功能节选,其他更多说明请查看官方邮件组和Git发版说明。

请从官方下载Git最新2.42版本,并进行升级。国内用户可以从镜像站下载最新安装包。

下载完成后注意核对安装包的文件哈希,保证其完整性和安全性。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OFYrkPA45J4OJFD889yAZQYQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券