玖叶教程网

前端编程开发入门

Git 2.34发布,功能亮点抢先学

日前开源Git开发讨论组宣布发布Git新版本2.34,我们今天就来学习一下新版本带来的一些亮点功能。

稀疏索引

对于大型的Git仓库,很多同学可以都尝试使用过过去,我们讨论过部分克隆(Partial clone)和稀疏检出(sparse checkout)。这两个功能可以协同工作,实现,仅获取或克隆存储库对象的一部分,在工作区只检出仓库小部分文件(目录),比一组子目录。但是实际上即使使用这些功能,Git的索引仍然是全局性质。Git索引是用来跟踪下一次运行git commit时将写入的内容的数据结构,以及在当前历史点跟踪存储库中每个文件的状态。

即使在大型存储库很小一部分用户空间修改,索引仍然要跟踪存储库的整个内容,而不仅仅是当前工作区这些文件。每个当Git需要使用索引时,它需要解析并写出大量数据,这些数据还会影响稀疏检出之外的存储库部分。

新版本中通过添加启用稀疏的索引,Git对此做了很大的优化。与之前版本的索引不同,新版本使索引能够仅跟踪关心的存储库部分。具体来说,只会包含仓库部分的条目,这些部分要么在稀疏检出中,要么在稀疏检出与存储库其余部分之间的边界处。

如上三角形代表树,方框代表文件blobs对象。左边为非稀疏索引内容的表示。右边为稀疏化索引,新版本中对底层blobs的访问极大的减小了。

多包可达性位图

功能可以启用可达性位图(Multi-pack reachability bitmaps)来跟踪存储在对象存储中多个包中的对象。在提供fetch服务时,Git服务器需要向客户端发送其想要的对象集中可访问的所有内容减去已经拥有的对象集中可以访问的内容。 (可以将克隆视为一种“特殊情况”获取,其中客户端想要一切而什么都没有)。

为了有效地计算该集合,Git使用可达性位图。其中之一.bitmapfiles存储一组位图,每个位图对应于某个提交。单个位图的内容是一串位,每个对象一个,指示每次提交可访问哪些对象。

之前可达性位图的内容与单个包文件中的对象顺序相关。这样位图只能覆盖一个pack文件中的对象。换句话说,位图只有在可以有效地将存储库的全部内容打包成一个单独的打包文件时才有用。

对于许多存储库,将所有对象写入同一个包是完全可行的。但是编写包所需的工作(包括搜索对象之间的增量、压缩单个对象和 I/O 成本)与正在编写的包的大小成比例。

Git 2.34 引入了一种全新的位图格式,该格式与多包索引的内容相关联文件。使用新格式位图现在可以灵活地表示多个包中的对象,并Git运营商不再需要将其最大的存储库重新打包到一个包中以充分利用可达位图的优势。

新的默认合并策略

当Git需要合并两个分支时,它会使用多个“策略”后端之一来解决更改或在两个更改无法协调时发出冲突。

多年来,Git 一直使用一种称为递归(recursive)的策略。 如果曾经在Git中进行过合并但没有通过 -s <strategy>,那么几乎可以肯定使用了递归引擎。递归的行为主要类似于标准的三向合并,只有一个例外。在“纵横交错”合并的情况下(没有单个合并基础),递归将多个碱基成对(递归地)合并在一起以生成单个树,然后将其视为新的合并基。这使得解决传统三向合并可能产生冲突的情况成为可能。

在最近的Git版本中,一直在努力替换递归策略与新策略ort(归的双胞胎,ostensibly recursive‘s twin)。为什么要这样做?有几个原因,最重要的重写允许Git实现不对索引进行操作的合并策略。

ort做到这一点:它是对合并策略的全面重写,旨在模仿递归同时避免了许多长期存在的性能和正确性问题。在包含许多重命名的合并中,ort大概是递归的500 倍。对于一系列类似的合并(如rebase操作),甚至可以快900倍,部分原因是ort的缓存和重用先前合并结果的能力。

这些数字展示了一些最坏的情况递归合并,但在测试中,ort一直领先递归策略而且方差要小得多。

在 Git 2.34 中,ort是默认的合并策略,因此应该注意到仅通过升级即可实现更快的合并和更少的错误。

全新的子模块

很多人可能听说过Git子模块功能,它允许通过存储指向其他存储库的链接来组合多个存储库。

我们知道大部分Git是用C编写的,但最初的git submodule命令实际上是一个shell脚本。

Git项目已经将许多用其他脚本语言编写的子命令转换为C重写。将子命令重新实现C程序意味着它们可以更容易地读写,利用Git的综合库,并避免产生许多进程的开销,尤其是在新进程开销昂贵的平台上。

Git 2.34 中,对子模块功能用C进行了重写。

为了使子模块中的对象和包含该子模块的存储库中的对象都可用于Git grep(在一组精选的其他命令),子模块将在该命令的持续时间内临时添加为替代。Git经进行了内部更改,以根据存储库(通常是全局存储库)来参数化许多函数。这允许Git避免通过交替组合多个存储库,而是通过传递两个(或更多)单独的存储库实例来进行函数调用。这使Git能够避免对替代机制的依赖,从而产生更少的混乱和容易出错的代码。

之前版本如果要克隆一个知道包含子模块的存储库,则使用--recurse-submodules,这会导致该存储库的子模块也被克隆和初始化。其他可以选择递归到子模块的命令(例如 git diff,例如)默认情况下本身不会递归到子模块中,即使您使用 --recurse-submodules。

Git 2.34 中,这种情况已经解决,克隆时 --recurse-submodules,会有一个警告其他命令仅在以下情况下递归到子模块中 submodule.stickyRecursiveClone设置配置,以防止命令在子模块中意外运行。

SSH密钥签名

Git数字签名很多人可能在用。通过PGP签名附加到某些对象。例如,Git项目本身发布由维护者签名的标签,以验证每个版本是否来自可信赖的人。

但是使用GPG和维护key的经验可以有点麻烦。一种替代方法是使用OpenSSH 的一项新功能(已发布 回到OpenSSH 8.0),允许使用可能已经拥有SSH密钥作为签名密钥。Git 2.34 支持利用该功能允许使用SSH密钥签署工作。

可以设置 user.signingKey到要使用的SSH 密钥(例如,通过命令ssh-agent询问列表ssh-add -L),或设置gpg.format到ssh和 gpg.ssh.defaultKeyCommand到ssh-add -以便自动使用第一个可用的SSH 密钥。

在配置Git以使用SSH密钥签署对象后,就可以像往常一样使用

git commit -S, git merge -S,和git tag -S

并自动使用SSH密钥签名。

总结

本文我们学习了Git 2.34带来一些亮点功能,当然还有其他功能可以参考官方的发布文档,可以说这个版本给我们带来很多惊喜的功能,尤其对大型仓库在性能方面的改善,大家可以下载尝试,可能会极大改善你当前遇到一些困境。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言