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

标签 git git-push

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

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

最佳答案

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

特别是,运行:

git push <em>remote</em> <em>refspec1 refspec2 ... refspecN</em>

在命令行上,您的 Git 在 remote 调用其他 Git(例如通过从 remote.<em>remote</em>.pushurl 获取的 URL)。然后你的 Git 向他们的 Git 交付由你的每个 refspecs 的源部分标识的对象,或者更准确地说,通过哈希 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 知道或假设他们的 Git 已经基于的对象进行增量压缩导致这一点的早期 have/want object-by-hash-ID 对话。 (例如,如果你提供了 a1234356 而他们说他们需要它,那么你提供了它的父 a000000 而他们说啊,我已经有了那个,你的 Git 知道他们不仅有对象 a000000 本身, 还有它的树和它的所有 blob。此外,如果他们的存储库不浅,他们有 a000000 的所有 parent 提交和所有 他们的 树和 blob !因此,您的 Git 可以针对所有此类较早的 blob 对 a123456 的 blob 进行增量压缩,以制作这个精简包。它可以完全省略 a123456 中也存在于 a000000 中的任何 blob,依此类推。)

一旦您的 Git 发送了精简包,另一端就会对其进行修复(加肥并添加索引)。他们现在采用您的 Git 请求集的形式:请将 设置为 (非强制推送)或没有(强制推送) ).如果您运行 git push origin a123456:name ,该请求会说 set name to a123456

他们要么服从请求/命令,要么拒绝。如果他们拒绝它,那么您刚刚发送给他们的 a123456 很可能无法从他们的任何其他引用中访问! (一种情况是,当 same 中的其他内容推送设置或更新一些 other 引用以使 a123456 可访问时。)

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

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

关于Git:将所有对象推送到远程存储库(不仅是引用,而且绝对是所有 blob、树和提交),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54805875/

相关文章:

git - 当两个对等方同时将更改推送到同一个远程时,git 是如何工作的

git - "Failed to connect to repository"设置 Github Jenkins 插件时出错

git - 在github上找一个force push的committer

git推送不起作用?

github 问题 - 错误 : failed to push some refs

git - 如何从另一个 Git 存储库中获取具有不同名称的子目录内容

git - 如何删除对 git 的提交

git - 为什么我不能用 git push origin :branchname? 删除远程 git 分支

Git:推送到时如何进行远程目录更新?

git - 如何防止 git 将更改推送到某些文件