Git如何确定需要在存储库之间发送哪些对象?

时间:2015-01-25 17:37:04

标签: git git-push git-pull git-fetch

我看过here,但无法弄清楚我想知道的事情:git pushgit pull如何找出另一边缺少的提交对象?

假设我们有一个包含以下提交的存储库:(字母代表SHA-1 ID,drefs/heads/master

a -> b -> c -> d
相反,遥控器有这些:

a -> e -> f -> g

根据git文档,遥控器会告诉我们它的refs/heads/master位于g,但由于我们不知道该提交,这实际上并没有告诉我们什么。如何找出缺失的数据呢?


另一方面,文件说:

  

此时,fetch-pack进程会查看它拥有的对象,并通过发送“want”然后发送它想要的SHA-1来响应它所需的对象。它使用“have”发送它已经拥有的所有对象,然后发送SHA-1。在此列表的末尾,它写入“done”以启动upload-pack进程以开始发送所需数据的packfile:

这解释了远程如何确定要发送的数据,但这不会影响具有许多对象的存储库的性能吗?否则,文本中实际意味着什么?


显然,数据传输的方式根据方向(推动与拉动)而有很大差异。这个设计选择面临的挑战是什么以及如何?我如何理解他们在文档中的描述?

1 个答案:

答案 0 :(得分:11)

神奇的是ID。提交ID由许多内容组成,但基本上它是SHA-1 hash

  • 内容(一切,不仅仅是差异)
  • 作者
  • 日期
  • 记录消息
  • 家长ID

更改其中任何一项,您需要使用新ID创建新提交。请注意,包含父ID。

这对Git意味着什么?这意味着如果我告诉你我已经提交了“ABC123”并且您提交了“ABC123”,我们知道我们拥有相同的内容,相同的作者,相同的日期,相同的消息和相同的父母相同的提交。这些父母具有相同的ID,因此他们具有相同的内容,相同的作者,相同的日期,相同的消息,和相同的父母。等等。如果ID匹配,它们必须具有相同的历史记录,则无需进一步检查该行。这是Git的强大优势之一,它深深地融入了它的设计中,没有它你就无法理解Git。

pull是一个fetch加上一个合并。 git pull origin mastergit fetch origingit merge master origin/master(或rebase --rebase)。 fetch看起来像这样......

remote @ http://example.com/project.git

                  F - G [bugfix]
                 /
A - B - C - D - E - J [master]
                     \
                      H - I [feature]

local
origin = http://example.com/project.git

                  F - G [origin/bugfix]
                 /
A - B - C - D - E [origin/master] [master]
  • [local]嘿,你有什么分支?
  • [remote]我在G。
  • 上有bugfix
  • [local]我在G上也有bug修复!完成。还有什么?
  • [遥远]我有我的特色。
  • [local]我没有特色也没有I.我的父母是什么人?
  • [remote]我的父母是H.
  • [local]我没有H,H的父母是什么?
  • [remote] H的父母是J。
  • [本地]我没有J. J的父母是什么?
  • [remote] J的父母是E。
  • [本地]我有E!请给我J,H和我。
  • [遥远]好的,他们来了。
  • [local] 将J,H和I添加到repo并将原点/功能放在我好的,你还有什么?
  • [遥远]我在J。
  • 掌握了
  • [本地]我在E大师,你已经发给我J. 将原点/主人移到J 。还有什么?
  • [遥远]就是这样!
  • [local] Kthxbi

现在本地看起来像这样......

local
origin = http://example.com/project.git

                  F - G [origin/bugfix]
                 /
A - B - C - D - E [master] - J [origin/master]
                              \
                               H - I [origin/feature]

然后它将git merge master origin/master完成拉动,这将快进到J。

推送类似,除了进程反向(本地发送提交到远程)并且它只会快进。

当你的远程服务器是一个简单的HTTP服务器时,这就是Pro Git refers to as "the dumb protocol"The Smart Protocol是经常使用的,不那么繁琐,并且有许多优化。但是你可以看到它们是如何非常高效的。没有必要传达整个历史记录,他们只需要发送20个字节的哈希键,直到找到共同的祖先。

以下是一些消息来源和进一步阅读。