在git clone和git push

时间:2015-11-04 05:45:43

标签: git

当我运行

等命令时
git push

git push origin master

我的回购看起来像

      B--C--D <- master
     /
    A--E--F <- foo-branch

和原点看起来像

A <- master

是否包括提交E和F?我理解,它通常不包括foo-branch,但所有提交仍然被推送?

同样,当我做的时候

git clone <some-remote-repo>

我知道我通常会得到一个分支(似乎通常是master),但是我也有其他分支的本地提交副本,即使我没有得到他们头部的指针吗? / p>

2 个答案:

答案 0 :(得分:3)

它部分取决于运输:git有&#34; dumb transports&#34; (例如使用http一次传输一个对象)和#34;智能传输&#34; (使用git://ssh://协议,其中两个gits相互协商,然后 - 如果接收方指示它可以 - 发送方构建一个&#34;瘦包&# 34。)

它也部分依赖于命令:例如,如果你要求&#34;浅&#34;克隆,或单个分支,你通常得到比你正常&#34;正常&#34;克隆。并且,当您运行git push时,您可以选择最初提供给远程存储库的特定提交ID(如果有),以及您希望它们使用哪些分支名称。

现在让我们忽略浅分支和单分支克隆。

举个例子:

  B--C--D  <- master
 /
A--E--F    <- foo-branch

git push origin master(其refspec可能等同于master:master,即您尚未配置异常推送),其中您的远程origin当前已提交A(它对A所拥有的分支标签无关紧要,只有它具有 A)并假设一个智能协议,握手和传输协议开始时非常像这样:

(your git) "what options do your support? I have thin-packs etc"
(their git) "I have thin-packs and ofs-delta and so on"
(your git) "ok, send me all your refs and their SHA-1s"
(their git) "refs/heads/master is <SHA-1 of A>"
(their git) "that's all I have"

此时,您的git知道需要提交来获取对远程的所有提交:这些是您在存储库中运行时将列出的提交{{1} (当然,填写git rev-list master ^A的实际SHA-1)。不需要排除其他SHA-1,因为远程A只有一个分支,其提示是提交origin

这在内部的工作方式是A运行git push(带git pack-objects),然后运行--thin,并将您提交的提交ID传递给它使用排除(git rev-list或前缀--not)来推送他们的git发送给你的所有提交ID(在我们的例子中,只是一个提交ID ^) 。请参阅A的文档,特别注意git rev-list选项(或使用浅克隆时--objects-edge)。

因此,--objects-edge-aggressive会输出提交git rev-list的ID,加上其树的ID以及所有树的子树和blob,除非总结(通过否定的ID,在这种情况下,排除提交D的{​​{1}})远程git必须已经拥有它们。然后它输出提交^A的ID及其树,使用相同的&#34;除非&#34;条件,等等。请注意,提交A有一个与之关联的源树;并假设提交C具有相同的树 - 例如,假设提交AC的还原。在这种情况下,无需发送C树:远程必须拥有它,因为远程已提交B

(这个对象查找可以通过位图进行优化。我认为,github博客文章描述了这些位图的开发,这些位图解决了遍历大量提交图的相当缓慢的过程,以便根据一些分支提示ID找到哪些对象必须已经存在于某个远程存储库中。这极大地帮助了它们,因为智能协议上的获取过程与push的对称:我们只是交换发送和接收角色。)

在任何情况下,C的输出都会为您A提供信息。这提供了要采用的所有对象ID(commit git rev-list,如果需要,它的树,以及任何需要的子树和blob;提交git pack-objects --thin和所需的对象;提交D和所需的对象),以及另外还有ID not 来执行:commit C及其对象,如果在B之前有提交,那些及其对象。 pack-objects步骤生成一个delta压缩包,其中&#34;取这些对象&#34;对象被压缩,不要带走这些其他对象&#34;对象。

作为一个超简化示例,假设A的树包含一个10 MB的文件,其最后一行是&#34;结束&#34;。假设A的树有一个几乎相同的文件,除了单词&#34;结束&#34;被删除。 Git可以将此文件压缩为说明&#34;以blob&lt; id-of-file&gt;开头,然后删除最后一行。&#34;这些说明长度远小于10 MB,并且允许使用&#34;瘦包&#34;。

这是&#34;薄包&#34;通过Internet-phone连接(或任何datawire连接两个git实例)发送的。然后接收器变厚&#34;将包打包成普通的git包(普通包不允许对包含在包中的对象进行delta压缩)。

好的,这很长,但归结为:你的git不会发送A(因为你没有问过),也没有{{1} (因为你没有发送B),也不会看到附加到这两个提交的两棵树。但这取决于您使用的确切命令,以及您是否使用智能协议。

如果您在没有F的情况下运行E,您的克隆操作将像往常一样调用遥控器,并获取远程参考的所有列表(就像推!)。要查看这些内容,请使用F

git clone

[数百个剪辑]

然后你的git从遥控器请求所有。 (在这种情况下,&#34;只是&#34;是不必要的,但如果他们向您展示除--single-branchgit ls-remote之外的From git://git.kernel.org/pub/scm/git/git.git aa826b651ae3012d1039453b36ed6f1eab939ef9 HEAD fdca2bed90a7991f2a3afc6a463e45acb03487ac refs/heads/maint aa826b651ae3012d1039453b36ed6f1eab939ef9 refs/heads/master 595b96af80404335de2a8c292cee81ed3da24d29 refs/heads/next 60feb01a0d7c7d54849c233d2824880c57ff9e94 refs/heads/pu 7af04ad560ab8edb07b498d442780a6a794162b0 refs/heads/todo d5aef6e4d58cfe1549adef5b436f3ace984e8c86 refs/tags/gitgui-0.10.0 3d654be48f65545c4d3e35f5d3bbed5489820930 refs/tags/gitgui-0.10.0^{} ,您可能无法获得这些。一些控制你的git带来了什么标签。这里的细节有点乱,但在大多数普通的存储库中,克隆将带来所有的标签。)

当你这么说时,你会因错误的假设而绊倒:

  

我知道我通常会得到一个分支(似乎通常是主人),但是我也有其他分支的本地提交副本,即使我没有得到指向他们的头部吗?

你的git要求并得到他们所有的分支。但你的git 也重命名。他们全部重命名为位于refs/名称空间内的远程名称(通常为heads/,但tags/refs/remotes/更改此名称)。他们的origin成为您的-o <name>;他们的--origin <name>成为您的refs/heads/master;等等。

通过运行refs/remotes/origin/master,您将看到所有这些(略有缩写),告诉refs/heads/maint显示远程跟踪分支。 (再次,&#34;远程跟踪分支&#34;只是那些全名以refs/remotes/origin/maint开头的分支。来自特定远程的git branch -r通过{更新相应的远程跟踪分支该遥控器的repo配置条目中的{1}}指令。)

如果您运行git branchrefs/remotes/,您看到的git fetch实际上是fetch =中的最后一步。它实际上并没有运行master - 它具有直接构建的相同代码 - 但实际上,您的克隆作为其最终操作,对某些分支名称运行git branch(或者,作为最后一次尝试,一个原始的SHA-1给了一个&#34;分离的HEAD&#34;)。使用的名称是:

  • 您作为参数提供给git status
  • 的那个
  • 远程git的clone指向的分支,如果您的分支可以解决这个问题,或者是在协议协商期间提供的分支。 1

如果这些失败 - 假设您没有指示git checkout进程进行结帐 - git checkout branch-or-sha1会检查原始SHA-1它来自遥控器作为遥控器git clone。 (在上面的示例HEAD输出中,这是clone。)

1 请注意git clone作为原始SHA-1出现。很长一段时间,git中有一个错误,如果这个SHA-1至少对应两个分支名称,HEAD不知道要检出哪个分支。因为智能协议首先通过协商选项,git人员能够添加一个选项,通过该选项,一个git告诉另一个&#34; HEAD指向分支X&#34;。现在,即使导入的ls-remote匹配多个导入的aa826b651ae3012d1039453b36ed6f1eab939ef9名称,git也可以告诉您使用哪个名称。

答案 1 :(得分:1)

内部运作的方式是git push运行git pack-objectswith --thin),然后运行git rev-list,并向其传递您要求推送的提交ID < / p>

可以通过位图优化此对象查找。

嗯,自从使用Git 2.4.7(2015年第三季度)以来就没有了

请参见commit c8a70d3Jeff King (peff)(2015年7月1日)。
(由Junio C Hamano -- gitster --commit ace6325中合并,2015年7月10日)

rev-list:修剪提交时禁用--use-bitmap-index

签名人:杰夫·金

可访问性位图没有足够的信息来告诉我们哪些提交可能已更改路径“ foo”,因此当前代码会产生以下错误答案:

git rev-list --use-bitmap-index --count HEAD -- foo

(它无​​声地忽略了“ foo”限制器)。 相反,我们应该退后一步进行正常遍历(退回而不是抱怨是可以的,因为--use-bitmap-index是纯粹的优化,并且可能由于其他原因(例如,存储库)。

在Git 2.26(2020年第1季度)中已注意到:对象可达性位图机制和部分克隆机制不准备很好地协同工作,因为部分克隆使用的某些对象筛选标准固有地依赖于对象遍历,但是位图机制是绕过对象遍历的优化。

但是,在某些情况下,他们可以一起工作,并且得到了有关他们的教导。

请参见commit 20a5fd8Junio C Hamano (gitster)(2020年2月18日)。
参见commit 3ab3185commit 84243dacommit 4f3bd56commit cc4aa28commit 2aaeb9acommit 6663ae0commit 4eb707ecommit ea047a8,{ {3}},commit 608d9c9commit 55cb10fcommit 792f811(2020年2月14日)和commit d90fe06commit e03f928commit acac50d(2020年2月13日)由commit 551cf8b
(由Jeff King (peff)Junio C Hamano -- gitster --中合并,2020年3月2日)

commit 0df82d9:拒绝使用pathspec进行位图遍历

签名人:杰夫·金

pack-bitmap(“ rev-list:修剪提交时禁用--use-bitmap-index”以来,

rev-list拒绝使用具有路径规范限制的位图”,2015-07-01,Git v2。 5.0-rc2-c8a70d3509)。
但这不仅适用于修订列表,而且适用于所有调用prepare_bitmap_walk()的人;该代码不具备处理这种情况的能力。

我们从来没有注意到,因为只有其他调用者永远不会通过pathspec限制器。

但是无论如何,让我们将支票下推到prepare_bitmap_walk()中。这是一个更合乎逻辑的地方,因为调用者不必知道详细信息(并且必须准备好退回常规遍历,因为存储库中可能没有位图)。

这也为我们做好了处理_is _案件的一天的准备,但这不太可能。例如,我们可以使用位图生成一组提交,然后对每个提交进行比较以查看其是否与pathspec匹配。
这比实际遍历提交的幼稚遍历要快一些。
但是您可能还是会做得更好,以利用较新的commit-graph功能来使提交变得非常便宜。


在Git 2.27(2020年第二季度)中,带有对象过滤器“ --filter=tree:0”的对象行走现在可以利用打包位图(如果可用)。

请参见mergecommit 9639474commit 5bf7f1e(2020年5月4日)。
请参见Jeff King (peff)commit b0a8d48commit 856e12c(2020年5月4日)。
(由Taylor Blau (ttaylorr)Junio C Hamano -- gitster --中合并,2020年5月13日)

commit 69ae8ff:使对象过滤功能通用

签名人:泰勒·布劳

pack-bitmap.c(“ pack-bitmap:实施BLOB_NONE过滤”中,2020-02-14,Git v2.26.0-rc0-4f3bd5606a在{{3 }}),为“ LOFC_BLOB_NONE”过滤器添加了对位图的过滤支持。

将来,我们希望增加对过滤器的支持,这些过滤器的行为就像它们排除了某种对象一样,例如,深度为0的树深过滤器。

为此,请使一些用于过滤的函数更加通用,例如“ find_tip_blobs”和“ filter_bitmap_blob_none”,以便它们可以处理任意对象类型。

为此,创建'find_tip_objects'和'filter_bitmap_exclude_type',并根据这些功能重新定义上述功能。

相关问题