Git Smart API 瘦包计算是否可以考虑重用常见的子树?

jav*_*ett 5 git git-push

Q:当 git 推送在Smart Protocol上没有共同历史的 refs 时,是否可以考虑在本地和origin构建 Thin-pack 时发送的根或子树已经是共同的?

tl;博士

在使用和推送到远程 Git 存储库时,请考虑这种(不常见的)情况。

  • 我有一个本地存储库,其中本地master指向具有 1110 个后代子树的树a[0-9]/b[0-9]/c[0-9]
  • 远程origin/master与本地master提交是最新的,即相同的历史记录。它使用ssh协议。
  • 无论出于何种原因,我创建了一个本地分支squashed。我将该分支设置为一个新的单根提交,但与master. 这可以通过git commit-tree. 所以,这个分支具有一个提交与常见,没有提交master,但根椐哈希值是相同的,它指向同一个树对象中masterorigin/master。为了讨论这个问题,这是一个单一/压缩的提交并不重要 - 任何历史重写回根提交,没有共同的历史都可以。
  • git push origin HEAD # push squashed

根据对大型存储库的性能以及发送的对象数量的观察,我怀疑push,send-pack以及receive-pack通过智能协议进行的相关瘦包协商会执行以下操作:

  • 确认被推送的提交squashedorigin当前的任何提交没有共同历史。
  • squashed没有注意到指向一棵树的事实,该树不仅在 中origin,而且是当前HEADref的树。
  • 打包并发送所有内容。

在这种情况下,树是相同的。如果在squashed... 中进行了后续更改,或者是附加提交,或者是更改了 中文件的新壁球a0,则 2 棵树(/a0)将发生更改,而其他 1109 将保持不变。根树发生了变化,这意味着需要进行下一级搜索以查看是否值得搜索进一步的公共子树。这可能需要启发式方法,因为如果不比较所有子树到叶子,就不可能从任何特定深度的树中推断出共同的后代树的数量。

当然,如果在推送的普通历史中有多个提交,则需要为每个提交重复此协商。

Smart API 在考虑每个提交时可以考虑已经持有的公共子树,或者至少考虑根树,这听起来合理吗?或者 Git 应该已经这样做了并且我的客户端或服务器有问题?

git version 2.8.2

jth*_*ill 2

检查 git 的源代码并使用 git daemon 和 GIT_TRACE_PACKET 尝试它,表明您对它所做的事情是正确的:git 仅在提交级别进行协商。如果不共享历史记录,git 将不会检测到共享内容。

智能 API 在考虑每次提交时可以考虑已经持有的公共子树,或者至少考虑根树,这听起来合理吗?

如果已经持有的公共子树无法通过已经持有的公共提交来识别,那么为了识别这些子树,它必须发送它们的 id。

问题是,对于任何缺乏完整读出的事情,我可以构建一个听起来合理的极端情况,发送任意大量的冗余数据——但每次都发送每个现有的子树 ID 以避免这种可能性显然是一个巨大的损失。不要忘记往返延迟的成本非常高。那么,在考虑所有提取的总体开销时,什么时候您可能会花费更多时间进行谈判?如果您认为某种特定的替代方法可以节省总体时间,那么您将必须提供有关实际生产流量的硬数据。

另请记住,您可以自己构建包。这并不难,您将对象 ID 提供给git pack-objects pack并将输出放入.git/objects/pack,恭喜,您刚刚将这些对象准确地提取到该存储库中。