【问题标题】:What do the numbers in the "Total" line of git gc/git repack output mean?git gc/git repack 输出的“Total”行中的数字是什么意思?
【发布时间】:2012-03-11 21:22:29
【问题描述】:

当我在我的 Git 存储库上运行 git gcgit repack 时,它会在完成后输出一个“总计”行。这些数字是什么意思?

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

$ 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) 手册页,并仔细阅读了他们的“另请参阅”,而我在 Google 上的尝试只产生了无关紧要的结果。

【问题讨论】:

标签: git git-gc


【解决方案1】:

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

Git 非常简单——我的意思是,简单到令人困惑!这个名字真的很适合它的设计,由于它的愚蠢,它非常聪明。

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

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

这就是 git gc 的用武之地。它只是解析 .git/objects 中的所有对象,标记出所有由 HEAD 或 BRANCH 以某种方式引用的对象。显然剩下的任何东西都是孤立的,与任何“重要”的东西无关,因此可以将其删除。这就是为什么如果您分支,在该分支上做一些工作,但后来放弃该分支并从您的 git 存储库中删除对它的任何引用,运行的定期 git gc 将完全清除您的分支。这可能会让一些老 VCS 用户感到惊讶,例如CVS 永远不会忘记任何事情,除非它自己崩溃或损坏(这种情况经常发生)。

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

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

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

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

希望这能回答您的问题。真正使用 git 它是如此简单,您会惊讶于它在开始时完全有效,然后当您将头绕在它周围时,您会被深深地留下深刻印象。只有真正的天才程序员才能写出如此简单却又如此出色的东西,因为他们可以看到大多数程序员只能看到复杂性的简单性。

尼尔

【讨论】:

  • 根据手册页,git gc 运行 git repack,所以说两者完全不同似乎是错误的。此外,前两个示例(都具有非零“重用”计数)来自一个只有一个包的存储库,所以你的解释对我来说没有意义。
  • 有 git repack 并且有 git repack - 如果我记得的话 git gc 做了一个“轻量级”的重新包装。关于重用计数,我的答案基于追踪德威的一个错误,其中“这个包的外部”参考没有得到满足,德威进入了无限循环。我会坦率地承认我没有检查过 git 代码以确保重用确实意味着我认为的意思。
  • 关于重用计数不会为零,请尝试 git repack -a 强制完全重新打包。我已经编辑了我的答案,以澄清我所说的“完全重新包装”的意思。此外,尝试在完全重新打包期间增加窗口和深度(请参阅linux.die.net/man/1/git-repack)。对于大型 repo,可能会保留一些掉在窗口外的重复使用的对象。
猜你喜欢
  • 2015-04-27
  • 2016-12-15
  • 1970-01-01
  • 2011-12-09
  • 1970-01-01
  • 2015-07-02
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
相关资源
最近更新 更多