Git 智能 API 精简包计算可以考虑重用公共子树吗?
Could Git Smart API thin pack calculation ever consider reusing common sub-trees?
问:当git将没有共同历史的refs推送到Smart Protocol时,是否可以在构建时考虑本地和origin
之间已经共有的根或子树要发送的薄包装?
tl;dr
在使用和推送到远程 Git 存储库时考虑这种(不常见的)情况。
- 我有一个本地存储库,其中本地
master
指向具有 1110 个后代子树的树 a[0-9]/b[0-9]/c[0-9]
。
- 远程
origin/master
与本地 master
提交是最新的,即相同的历史记录。它使用 ssh
协议。
- 出于某种原因,我创建了一个本地分支
squashed
。我将该分支设置为一个新的单根提交,但 content/tree 与 master
相同。这可以用 git commit-tree
来完成。所以这个分支只有一个提交,没有与 master
共同的提交,但是根树哈希是相同的,它指向 master
和 origin/master
中的同一个树对象。为了讨论这个问题,这是一个 single/squashed 提交并不重要 - 任何历史重写回根提交,没有共同的历史都可以。
git push origin HEAD # push squashed
根据对大型存储库的性能和发送的对象数量的观察,我怀疑 push
、send-pack
和 receive-pack
以及相关的精简包协商在 Smart Protocol 上做了类似的事情:
- 确认被推送的提交
squashed
与任何提交 origin
当前拥有的没有共同历史。
- 没有注意到
squashed
指向的树不仅在 origin
中,而且是当前 HEAD
ref. 的树
- 打包并发送所有内容。
在这种情况下,树是相同的。如果在 squashed
中进行了后续更改......要么是额外的提交,要么是在 a0
中更改文件的新压缩,2 棵树(/
和 a0
)会发生变化,而其他 1109 将保持不变。根树已更改,这意味着需要进行下一级搜索以查看是否值得搜索更多公共子树。这可能需要启发式方法,因为如果不比较所有子树到叶子,就不可能从任何特定深度的树中推断出共同后代树的数量。
当然,如果在被推送的无共同历史记录中有多个提交,则需要为每个提交重复此协商。
Smart API 可以在考虑每次提交时考虑已经存在的公共子树,或者至少是根树,这听起来合理吗?或者 Git 应该已经在执行此操作并且我的客户端或服务器有问题吗?
git version 2.8.2
检查 git 的源代码并用 git 守护程序尝试它,GIT_TRACE_PACKET 说你对它所做的是正确的:git 在提交级别协商只要。如果未共享历史记录,git 将不会检测共享内容。
Does it sound reasonable that the Smart API could consider already-held common sub-trees, or at the very least, the root-tree, as it considers each commit?
如果已经持有的公共子树不能被已经持有的公共提交识别,那么为了识别那些子树,它必须发送它们的 ID。
问题是,对于没有完整读出的任何东西,我可以构建一个听起来似是而非的角落案例,发送任意大量的冗余数据——但每次都发送每个现有的子树 ID 以避免这种可能性显然是巨大的损失。不要忘记往返延迟非常昂贵。那么,在考虑 all 提取的总开销时,您在什么时候可能会花更多时间进行谈判?如果您要争辩说某些特定的替代方法可以节省总体时间,那么您将不得不提供有关实际生产流量的硬数据。
另请记住,您可以自己构建包。这并不难,您将对象 ID 提供给 git pack-objects pack
并将输出放入 .git/objects/pack
,恭喜,您刚刚将这些对象准确地提取到该存储库中。
问:当git将没有共同历史的refs推送到Smart Protocol时,是否可以在构建时考虑本地和origin
之间已经共有的根或子树要发送的薄包装?
tl;dr
在使用和推送到远程 Git 存储库时考虑这种(不常见的)情况。
- 我有一个本地存储库,其中本地
master
指向具有 1110 个后代子树的树a[0-9]/b[0-9]/c[0-9]
。 - 远程
origin/master
与本地master
提交是最新的,即相同的历史记录。它使用ssh
协议。 - 出于某种原因,我创建了一个本地分支
squashed
。我将该分支设置为一个新的单根提交,但 content/tree 与master
相同。这可以用git commit-tree
来完成。所以这个分支只有一个提交,没有与master
共同的提交,但是根树哈希是相同的,它指向master
和origin/master
中的同一个树对象。为了讨论这个问题,这是一个 single/squashed 提交并不重要 - 任何历史重写回根提交,没有共同的历史都可以。 git push origin HEAD # push squashed
根据对大型存储库的性能和发送的对象数量的观察,我怀疑 push
、send-pack
和 receive-pack
以及相关的精简包协商在 Smart Protocol 上做了类似的事情:
- 确认被推送的提交
squashed
与任何提交origin
当前拥有的没有共同历史。 - 没有注意到
squashed
指向的树不仅在origin
中,而且是当前HEAD
ref. 的树
- 打包并发送所有内容。
在这种情况下,树是相同的。如果在 squashed
中进行了后续更改......要么是额外的提交,要么是在 a0
中更改文件的新压缩,2 棵树(/
和 a0
)会发生变化,而其他 1109 将保持不变。根树已更改,这意味着需要进行下一级搜索以查看是否值得搜索更多公共子树。这可能需要启发式方法,因为如果不比较所有子树到叶子,就不可能从任何特定深度的树中推断出共同后代树的数量。
当然,如果在被推送的无共同历史记录中有多个提交,则需要为每个提交重复此协商。
Smart API 可以在考虑每次提交时考虑已经存在的公共子树,或者至少是根树,这听起来合理吗?或者 Git 应该已经在执行此操作并且我的客户端或服务器有问题吗?
git version 2.8.2
检查 git 的源代码并用 git 守护程序尝试它,GIT_TRACE_PACKET 说你对它所做的是正确的:git 在提交级别协商只要。如果未共享历史记录,git 将不会检测共享内容。
Does it sound reasonable that the Smart API could consider already-held common sub-trees, or at the very least, the root-tree, as it considers each commit?
如果已经持有的公共子树不能被已经持有的公共提交识别,那么为了识别那些子树,它必须发送它们的 ID。
问题是,对于没有完整读出的任何东西,我可以构建一个听起来似是而非的角落案例,发送任意大量的冗余数据——但每次都发送每个现有的子树 ID 以避免这种可能性显然是巨大的损失。不要忘记往返延迟非常昂贵。那么,在考虑 all 提取的总开销时,您在什么时候可能会花更多时间进行谈判?如果您要争辩说某些特定的替代方法可以节省总体时间,那么您将不得不提供有关实际生产流量的硬数据。
另请记住,您可以自己构建包。这并不难,您将对象 ID 提供给 git pack-objects pack
并将输出放入 .git/objects/pack
,恭喜,您刚刚将这些对象准确地提取到该存储库中。