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

Git如何确定需要在存储库之间发送哪些对象?,git,git-push,git-pull,git-fetch,Git,Git Push,Git Pull,Git Fetch,我已经看过了,但不能完全弄清楚我想知道的事情:如何git push或git pull找出另一端缺少哪些提交对象 假设我们有一个具有以下提交的存储库:(字母代表SHA-1 ID,disrefs/heads/master) 相反,遥控器具有以下功能: a -> e -> f -> g 根据git文档,遥控器会告诉我们它的refs/heads/master位于g,但是因为我们不知道提交,所以实际上没有告诉我们任何事情。这怎么足以找出丢失的数据 另一方面,该文件说: 此时,fetc

我已经看过了,但不能完全弄清楚我想知道的事情:如何
git push
git pull
找出另一端缺少哪些提交对象

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

相反,遥控器具有以下功能:

a -> e -> f -> g
根据git文档,遥控器会告诉我们它的
refs/heads/master
位于
g
,但是因为我们不知道提交,所以实际上没有告诉我们任何事情。这怎么足以找出丢失的数据


另一方面,该文件说:

此时,fetchpack进程将查看它拥有哪些对象,并通过发送“want”和它想要的SHA-1来响应它所需要的对象。它用“have”发送它已经拥有的所有对象,然后发送SHA-1。在该列表的末尾,它写上“完成”以启动上传包过程,开始发送所需数据的包文件:

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



显然,数据传输的方式因方向(推或拉)的不同而大不相同。这个设计选择遇到了哪些挑战?如何应对这些挑战?我如何理解文档中的描述?

IDs的魔力在于。提交ID由很多东西组成,但基本上是由这些东西组成的

  • 内容(一切,而不仅仅是差异)
  • 作者
  • 日期
  • 日志消息
  • 父ID
更改其中任何一个,您都需要使用新ID创建一个新的提交。请注意,其中包括父ID

这对Git意味着什么?这意味着,如果我告诉你我提交了“ABC123”,而你提交了“ABC123”,我们就知道我们有相同的提交,内容相同,作者相同,日期相同,信息相同,父母相同。这些父母有相同的ID,所以他们有相同的内容、相同的作者、相同的日期、相同的消息和相同的父母。等等如果ID匹配,则它们必须具有相同的历史记录,无需进一步检查。这是Git最大的优点之一,它深深地融入到它的设计中,没有它你无法理解Git

pull是一个fetch加上一个merge
git-pull-origin-master
git-fetch-origin
加上
git-merge-master-origin/master
(或
rebase
--rebase
)。抓取看起来像这样

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
origin = http://example.com/project.git

                  F - G [origin/bugfix]
                 /
A - B - C - D - E [master] - J [origin/master]
                              \
                               H - I [origin/feature]
  • [本地]嘿,remote,你们有哪些分支机构
  • [远程]我在G
  • [本地]我在G也有错误修正!完成。还有什么
  • [远程]我在I上有功能
  • [本地]我没有特征,也没有我。我的父母是什么
  • [remote]我的父母是H
  • [当地]我没有H,H的父母是什么
  • [remote]H的父母是J
  • 我没有J.J的父母是什么
  • [远程]J的父母是E
  • [当地]我有一个电子游戏!请寄给我J,H和我
  • [遥控器]好了,他们来了
  • [本地]将J、H和I添加到回购协议中,并将原点/特征放在I上。好的,您还有什么
  • [遥控器]我在J
  • [本地]我在E有大师,你已经把J.移动原点/大师到J.还有什么
  • [遥控]就是这样
  • [本地]Kthxbi
现在本地的看起来像这样

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
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服务器时所使用的。是使用频率更高的,不太健谈,并且有很多优化。但你可以看到这两种方法都非常有效。不需要交流整个历史,他们只需要发送20字节的散列键,直到找到一个共同的祖先

这里有一些资料来源和进一步的阅读


您的回答很好,谢谢!如果你不介意的话,我对如何避免往返特别感兴趣。这仅仅是一个急切地发送例如多达50个散列的问题(而且,如果你碰巧有任何答案的来源,这将是非常好的。我更关心的是“实现一个类似git的同步机制”,所以我完全满意,但未来的读者会寻找“git的同步是如何实现的细节”可能会很感激。@SillyFreak我添加了一些参考资料以进一步了解细节。对话示例是我如何从概念上教授它,Pro Git称之为什么。你想看一个更有效的示例。智能协议是我首先看到的,引用的,并要求澄清的。但我将研究代码很丰富,谢谢。@SillyFreak我想我现在理解智能协议了。如果你问一些关于智能协议的具体问题,我可能会提供帮助。只要把它们链接到这里,我一定会看到的。