开源Git项目刚刚发布了Git 2.31,其中包含85个贡献者的功能和错误修复,其中23个新的。上次我们赶上了你,Git 2.29刚刚被释放。稍后两个版本,让我们来看看自从此发生的最有趣的功能和变化。
图片:你在你的终端,写作提交,从另一个存储库中拉动,并在突然突然推出结果,你是由这个不友好的消息打招呼:
自动打包存储库以获得最佳性能。你可以alsorun" git gc"手动。查看" git帮助gc"欲获得更多信息。
......,你被困。现在你必须等待git完成跑步git gc --auto,然后才能回到工作。
这里发生了什么?在正常使用过程中,Git写了大量数据:对象,包装,引用等。其中一些路径是针对写性能进行的优化。例如,编写单个“松散”对象更快,但读取包文件更快。
要使您持续生产,Git会进行折衷:一般来说,它在您工作时为写路径进行优化,每次暂停其内部数据结构,以便更有效地读取长期以来一直保持富有成效。
Git有自己的启发式信息,何时是何时执行此类“暂停”,但有时候那些启发式触发最糟糕的时间触发阻塞Git GC。您可以自己管理这些数据结构,但您可能不希望投资时间讨论何时何时以及如何做到这一点。
从Git 2.31开始,您可以获得与背景维护的世界上最好的。此跨平台功能允许Git保留您的存储库健康,同时不会阻止您的任何交互。特别是,这将通过预先获取每小时从遥控器中预订最新对象来改善您的GIT获取时间。
开始后台维护的入门不能更容易。只需将终端导航到您要启用后台维护的任何存储库,并运行以下内容:
......而Git将照顾其余的。除了每小时预先获取最新的物体,Git也将确保其自己的数据也是组织。它将每小时一次更新其提交图文件,并将任何松散的对象(以及逐渐重新包装包装)包装。
在GIT维护文档中阅读有关此功能的更多信息,并学习如何使用维护自定义。*配置选项。如果您有任何问题,可以检查故障排除文档。
您可能知道Git将所有数据存储为“对象:”提交,树木和Blob,它存储单个文件的内容。为了效率,Git将许多对象放入PackFiles,这些对象基本上是一个连接的对象流(同一流也是通过Git获取和Git推送对象的方式。为了有效访问单个对象,Git为每个PackFile生成索引。这些.idx文件中的每一个允许将对象ID快速转换为包文件中的字节偏移量。
当你想进入另一个方向时会发生什么?特别是,如果所有Git都知道它在某些PackFile中看到的字节是什么,它是如何弄清楚字节是部分的?
为实现此目的,Git使用适当命名的反向索引:PackFile中的位置之间的不透明映射,并且每个位置的对象是其中的一部分。在git 2.31之前,没有用于反向索引的磁盘格式(如对于.idx文件),因此它必须在每次中生成并存储内存中的反向索引。这大致归结为生成对象位置对数组,然后按位置对数组进行排序(对于好奇,可以在此处找到确切的细节)。
但这需要时间。在具有大包装文件的存储库的情况下,这可能需要很多时间。为了更好地了解规模,考虑一个实验,该实验比较打印对象的大小所需的时间,而不是打印该对象的内容的时间。为了简单地打印对象的内容,Git使用前进索引来定位包中的所需对象,然后重新组装并打印其内容。但要在PackFile中打印对象的大小,Git不仅要定位我们要测量的对象,而且紧接着它的对象,然后减去两者以找出它使用了多少空间。要在相邻对象中找到第一个字节的位置,Git需要使用反向索引。
比较这两个,打印对象的大小比要打印整个对象的内容,它比打印的大小慢62倍。您可以通过运行通过HyperFine在家中尝试:
$ git rev-parse头> tip $ hyperfine --warmup = 3 \' git cat-file --batch< tip' \' git cat-file - 咬 - 检查="%(对象化:磁盘)" <提示'
在2.31中,GIT获得了与.Rev扩展的新磁盘格式序列化反向索引。在生成磁盘反向索引并重复上述实验后,我们的结果表明,在其大小的情况下打印对象的内容需要大致相同的时间。
敏锐的读者可能会问自己为什么需要使用反向索引来打扰的git。毕竟,如果可以打印对象的内容,那么肯定打印该对象的大小并不比知道打印内容时写入多少字节。但是,这取决于对象的大小。如果它是巨大的,那么计算所有字节都比简单的减去更昂贵。
反向索引可以帮助超越合成实验,如这些:当向获取或推送发送对象时,反向索引用于直接从磁盘发送对象字节。提前计算的反向指数使得此过程运行得更快。
Git默认情况下不会生成.REV文件,但您可以通过运行Git Config Pack.WriteReverseIndex True来尝试自己,然后重新包装存储库(带Git Repack -Ad)。我们在Github上使用了这几个月,以便在许多不同的GIT操作中实现戏剧性的改进。
在The Commit-Graph文件之前,我们在此博客上介绍了此博客。这是一个有关提交的常见信息的非常有用的序列化,与他们拥有的父母一样,他们的根树是什么,依此类推。 (对于更详细的博览会,博客帖子系列开始这里是一个很好的博览会)。提交图还存储有关提交的生成号码的信息,可以用于加速许多种类的散步。在Git 2.31中,使用了一种新的一代数量,这可以在某些情况下进一步提高性能。这些补丁是由代码学生的谷歌夏季的Abhishek Kumar贡献。
在最近的Git版本中,在具有init.defaultbranch配置的新存储库中更容易更改主分支的默认名称。 Git一直试图检查遥控器头部的分支(即,如果遥控器的默认分支是“foo”,则Git Clone会尝试在本地结账),但这尚未使用空的存储库.in Git 2.31,现在也适用于空的存储库。现在,如果您克隆了在本地创建的新创建的存储库开始编写第一个修补程序时,您的本地副本将尊重遥控器设置的默认分支名称,即使还有任何提交。
在重命名事物的主题上,Git 2.30使更改更改另一个默认值的名称:存储库的首个遥控器。当GIT克隆存储库时,第一个远程初始化始终命名为“源”.PROR到GIT 2.30,重新命名的选项仅限于运行Git远程重命名源< newname&gt ;. Git 2.30允许您配置默认情况下选择其他名称,而不是始终使用“源”。要为自己提供尝试,请设置clone.defaultremotename配置。
当存储库变大时,很难弄清楚哪个分支负责。在Git 2.31中,Git Rev-list现在具有 - Disk-Usage选项,它既比使用现有工具总结对象大小的速度更大且速度。 Rev-List手册的示例部分显示了一些使用(并查看下面的源链接以进行时间,并查看“旧”方式)。
您可能已经使用git的-g<正则表达式>找到修改提交的行的提交的选项(例如,git log -g' foo \('将查找为foo()函数的调用)。但是,您也可能忽略匹配某个模式的行。Git 2.30介绍-i< regex>,它允许您忽略与正则表达式匹配的行中的更改。例如,git log -p -i' //# 39;将显示每个提交的补丁,但省略了只触及注释行的任何人(包含//)。
在准备更换合并后端的准备时,重命名检测已经大大优化。您可以在优化Git的合并机械,#1和优化Git的合并机械,#2中了解更多有关这些更改的更多信息。
这只是过去几对释放的变化示例。有关更多,请在GIT存储库中查看2.30和2.31中的发行说明或以前的版本。