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

时间:2019-02-21 11:20:18

标签: git git-push

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

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

1 个答案:

答案 0 :(得分:4)

简短的回答是,你做不到,不是很清楚。 git push推送/上传各种Git对象时,它的结束是在另一个Git存储库中设置一个或多个名称。然后,接收方Git倾向于随后立即运行git gc

特别是 you 运行:

git push remote refspec1 refspec2 ... refspecN

在命令行上,您的Git在 remote (例如,从remote.remote.pushurl提取的URL)中调用了其他一些Git。然后,您的Git将由每个refspec的源部分标识的对象传递到其Git,或更准确地说,通过哈希ID将这些对象提供给他们。您可以在此处放置哈希ID:

git push origin a123456:name

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

最终,您的Git和他们的Git同意,如果您的Git发送了一些对象集,它们将具有接受(或拒绝!)您的Git的设置一些名称请求所需的所有对象。然后,您的Git打包这些对象,通常是薄包,用于存储这些对象,但会对您的Git 知道或假定的对象进行Delta压缩。导致这一点的较早的有/想要通过散列ID进行对话。 (例如,如果您提供了a1234356,他们说他们需要它,那么您提供了其父项a000000,他们说了啊,我已经有了那个,您的Git知道他们不仅拥有对象a000000本身,而且拥有其树及其所有blob。此外,如果其存储库不是浅的,则它们具有a000000的所有 parent 提交以及所有树和blob!因此,您的Git可以针对所有此类较早的blob对a123456的blob进行delta-compressing,以使它变薄,从而可以完全忽略任何blob。在a123456中也同样在a000000中,依此类推。)

一旦您的Git发送了瘦包,另一侧便对其进行修复(将其填充并添加索引)。现在,它们采用您Git的一组请求形式:请设置 (非强制推送),或者不设置 please (强制推送) )。如果您运行了git push origin a123456:name,则该请求会说name设置为a123456

他们要么服从请求/命令,要么拒绝它。如果他们拒绝,那么您刚发送给他们的a123456(很可能无法从他们的其他引用中获取) ! (一种情况是,相同推送集中的其他内容或更新了某些 other 引用,以使a123456可以访问。)

对话结束后,将所有设置设置为 后,他们运行git gc。如果您发送的对象是 loose 对象,则这些对象将受到默认的14天宽限期的保护。但是您给他们发送了一个打包文件。如果他们在合并对象的同时重新打包文件,他们将几乎一直这样做-他们将删除任何未引用的对象。

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