Git:将所有对象推送到远程存储库(不仅仅是引用,但绝对是所有blob,树和提交)

问题描述 投票:2回答:1

上下文:我(错误)使用Git不用于版本控制,而是记录文件之间的关系。 Git的内部数据结构(基本上是一个对象图)正是我所需要的(加密哈希等等),并且有很多非常好的工具来操纵数据。

到目前为止,我无法做的一件事是将整个图形推送到远程存储库。据我了解,git push只对refs,而不是objects。是否有一种简单的方法将所有对象(提交,树,blob)推送到远程,或者我必须首先在每个提交上添加ref(例如branch),然后推送所有分支,然后删除所有分支(本地和远程)?

git git-push
1个回答
4
投票

简短的回答是,你不能,不完全。当git push推送/上传各种Git对象时,它通过在另一个Git存储库中设置一个或多个名称而结束。然后接收Git会立即运行git gc

特别是,你运行:

git push remote refspec1 refspec2 ... refspecN

在命令行上,你的Git在remote调用了一些其他的Git(例如通过从remote.remote.pushurl获取的URL)。然后你的Git向你的Git提供由你的每个refspecs的源部分标识的对象,或者更确切地说,通过哈希ID为它们提供这些对象。您可以在此处输入哈希ID:

git push origin a123456:name

a123456是缩写的哈希ID。无论名称是什么对象,您的Git都会向其他Git提供完整的哈希ID。然后另一个Git将检查它是否有对象a123456。如果是这样,它告诉你它不需要实际的内容;如果没有,你的Git将打包内容,现在必须提供a123456所需的任何对象。例如,如果a123456是一个提交,你的Git必须提供它的树和父提交;另一个Git告诉你它是否已经拥有它们,或者需要它们,这会根据需要触发更多的对象跟踪。 (这里有一些优化可以减少来回通信,但这一点应该清楚。)

最后,你的Git和他们的Git同意,如果你的Git发送了一些对象,他们将拥有他们需要接受(或拒绝!)你的Git设置一些名称请求的所有对象。然后你的Git打包这些对象,通常是一个瘦包,它存储这些对象,但是对Git知道或假设Git已经拥有的对象进行增量压缩 - 基于之前的/想要的逐个哈希ID对话导致了这一点。 (例如,如果你提供a1234356并且他们说他们需要它,那么你提供了它的父亲a000000他们说啊,我已经有那个,你的Git知道他们不仅有对象a000000本身,而且它的树和所有而且,如果他们的存储库不浅,他们拥有所有a000000的父提交以及他们所有的树和blob!所以你的Git可以对所有这些早期的blob进行delta压缩a123456的blob,以制作这个薄包。可以完全省略a123456中也存在于a000000中的任何blob,依此类推。)

一旦你的Git发送了瘦包,另一方就修复了它(增加它并增加一个索引)。他们现在接受你的Git的表单请求集:请将<name>设置为<hash>(非强制推送)或者不设喜欢(强制推送)。如果您运行git push origin a123456:name,该请求会将name设置为a123456

他们要么遵守请求/命令,要么拒绝它。如果他们拒绝它,那么你发送它们的a123456很可能无法从其他任何引用中获得! (它的一种情况是,在同一个推送集中的其他东西或更新其他参考,以便使a123456可达。)

当对话结束后,在所有set <name>到<hash>操作之后,他们运行git gc。如果您发送的对象是松散的对象,那么这些对象将受到默认的14天宽限期的保护。但是你给他们发了一个包文件。如果他们重新打包包文件,同时合并他们将要保留的对象 - 他们几乎总是这样做 - 他们将丢弃任何未引用的对象。

这导致了一个有些悲伤的结论,构成了这个答案的第一句话。

© www.soinside.com 2019 - 2024. All rights reserved.