git gc / git repack输出的“Total”行中的数字是什么意思?

时间:2012-02-21 14:57:42

标签: git git-gc

当我在我的Git存储库上运行git gcgit repack时,它会在完成后输出“Total”行。这些数字意味着什么?

来自相当小的存储库的几个例子:

$ git gc
...
Total 576 (delta 315), reused 576 (delta 315)

$ git repack -afd --depth=250 --window=250
...
Total 576 (delta 334), reused 242 (delta 0)

来自更大的存储库中的一个:

$ git gc
...
Total 347629 (delta 289610), reused 342219 (delta 285060)
...

我可以猜出第一个“Total”数字是什么:存储库中Git对象(如提交,树和文件)的数量。所有其他人实际上意味着什么?

我已经查看了git-gc(1)git-repack(1)手册页,并仔细阅读了他们的“See also”,而我在谷歌搜索中的尝试只会产生不相关的结果。

1 个答案:

答案 0 :(得分:25)

我使用dulwich做了一些工作,这是Git的纯python实现。我在这里要说的是反映我对dulwich的git实现的体验,而不是规范的git源,因此可能存在差异。

Git非常简单 - 我的意思是,这么简单就让人感到困惑!这个名字非常适合它的设计,由于它的愚蠢而非常聪明。

当你提交任何内容时,git会获取索引(暂存区域)中的内容并创建SHA摘要项,因此每个文件都会获得SHAed,并且每个目录中的文件都会作为blob对象获得SHAed,当然目录结构会以树形式获取SHAed对象,以及绑定到也具有SHA的提交对象的所有对象。 Git只是在处理提交时直接将这些内容激发到.git / objects中的文件系统中。如果成功解雇了所有这些,它只是将最近提交对象的SHA写入.git / refs / heads /.

有时提交可能会失败一半。如果某些内容无法写入.git / objects,那么 git当时不会进行清理。那是因为通常你会修复问题并重做提交 - 在这种情况下,git将从之前停止的地方完全重启,即提交的一半。

这里是git gc的用武之地。它只是解析.git / objects中的所有对象,标记所有由HEAD或BRANCH以某种方式引用的对象。显然遗留的任何东西都是孤儿,与“重要”的东西无关,所以可以删除它。这就是为什么如果你分支,在那个分支上做一些工作但后来放弃那个分支并从你的git repo中删除对它的任何引用,运行的周期性git gc将完全清除你的分支。这可能会让一些旧的VCS用户感到惊讶CVS永远不会忘记任何事情,除非它自身崩溃或损坏(通常是这样)。

git repack(真正的git-pack-objects)与git gc完全不同(例如,一个单独的命令和操作虽然git gc可能会调用git repack)。正如我之前提到的,git只是将所有东西都激活到它自己的SHAed文件中。它在进入光盘存储之前会对它们进行gzip,但从长远来看,这显然不是空间效率。所以git-pack-objects的作用是检查一系列SHA对象,以便在数据在修订版本之间复制的任何地方。它并不关心它是什么类型的SHA对象 - 所有被认为是相同的包装。然后它生成有意义的二进制增量,并将整个批次存储为.git / objects / pack中的.pack文件,从正常目录结构中删除任何打包对象。

请注意,如果最新的pack文件大小小于1Mb,git-pack-objects通常会生成一个新的.pack文件,而不是替换现有的.pack文件。因此,随着时间的推移,您会看到多个.pack文件出现在.git / objects / pack中。实际上,当你进行git fetch时,你只需要让远程repo打包所有解压缩的项目,并将获取repo所没有的.pack文件发送到获取repo。 git repack只是调用git-pack-objects,但告诉它合并.pack文件,因为它认为合适。这意味着解压缩任何已更改的内容,重新生成二进制增量并重新压缩。

因此,要回答您的问题,总行数是指git仓库中的对象总数。第一增量数是作为二进制增量对象的那些总对象的数量,即git已经确定的对象具有与其他对象的强相似性并且可以存储为二进制增量。重用的数字表示正在使用来自压缩源(即包文件)的对象的数量,而没有被重新压缩以包括更近期的更改。当您有多个packfiles但更新的SHA对象引用旧packfile中的项作为其基础时,会发生这种情况,然后对它应用增量以使其现代化。这让git可以使用以前压缩的旧数据修订版,而无需重新压缩它以包含更新的添加内容。请注意,git可能会附加到现有的包文件而不会重写整个包文件。

一般来说,高重用计数表示可以使用完全重新包装(即git repack -a)回收一些空间,该重新包装将始终返回重用为零。但是,通常git会默默地为您处理所有这些。此外,执行完全重新打包可能会强制某些git提取从头开始重新启动,因为这些包不同 - 这取决于服务器设置(允许自定义每个客户端包生成在服务器CPU上很昂贵,因此一些主要的GIT站点禁用它)。

希望这能回答你的问题。真的很简单,你很惊讶它一开始就很有效,然后当你绕过它时,你会感到非常深刻的印象。只有真正的天才程序员才能编写如此简单而又运行良好的东西,因为他们可以看到大多数程序员只能看到复杂性的简单性。

尼尔