当我运行
等命令时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>
答案 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
具有相同的树 - 例如,假设提交A
是C
的还原。在这种情况下,无需发送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-branch
和git 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 branch
或refs/remotes/
,您看到的git fetch
实际上是fetch =
中的最后一步。它实际上并没有运行master
- 它具有直接构建的相同代码 - 但实际上,您的克隆作为其最终操作,对某些分支名称运行git branch
(或者,作为最后一次尝试,一个原始的SHA-1给了一个&#34;分离的HEAD&#34;)。使用的名称是:
git status
或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-objects
(with--thin
),然后运行git rev-list
,并向其传递您要求推送的提交ID < / p>可以通过位图优化此对象查找。
嗯,自从使用Git 2.4.7(2015年第三季度)以来就没有了
请参见commit c8a70d3的Jeff 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 20a5fd8的Junio C Hamano (gitster
)(2020年2月18日)。
参见commit 3ab3185,commit 84243da,commit 4f3bd56,commit cc4aa28,commit 2aaeb9a,commit 6663ae0,commit 4eb707e,commit ea047a8,{ {3}},commit 608d9c9,commit 55cb10f,commit 792f811(2020年2月14日)和commit d90fe06,commit e03f928,commit 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
”的对象行走现在可以利用打包位图(如果可用)。
请参见merge的commit 9639474,commit 5bf7f1e(2020年5月4日)。
请参见Jeff King (peff
)的commit b0a8d48,commit 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
',并根据这些功能重新定义上述功能。