git fetch和git fetch源主机之间的差异
我是,我想知道这两者之间是否有区别git fetch和git fetch源主机之间的差异,git,git-merge,git-fetch,Git,Git Merge,Git Fetch,我是,我想知道这两者之间是否有区别 git fetch 及 我在GitHub上没有指向我的远程存储库的任何其他分支和原点 当我这样做时: git fetch origin master remote: Counting objects: 4, done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (3/3
git fetch
及
我在GitHub上没有指向我的远程存储库的任何其他分支和原点
当我这样做时:
git fetch origin master
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From github.com:XXXXXXXXXXXXXXX
* branch master -> FETCH_HEAD
但只是:
git fetch
From github.com:XXXXXXXXXXXXXXX
531d466..aaf6df0 master -> origin/master
请注意,master指向不同的事物;在一种情况下,FETCH_HEAD
,在另一种情况下,origin/master
?
它们不同吗 这里是“TL;DR”版本(它掩盖了许多特殊情况):git fetch
总是更新fetch\u HEAD
,在各种情况下都有多行。它有时会更新“远程分支”,即全名以refs/remotes/
开头的refs。其余的大部分是关于“有时”的,这取决于给定给git fetch
的参数数量和git版本
我有机会测试一下。让我们区分三种情况,所有这些情况都假设运行git fetch
,而不需要像-a
甚至-all
这样的额外选项。让我们也排除git fetch
更奇怪的变体,比如直接使用URL,或者使用代替条目,或者.git/remotes
或.git/branchs
中列出的文件。(我承认我只是在猜测,但我认为这些都是在[remote“name”]
条目进入git配置文件之前的几天遗留下来的。编辑,2019:结果证明是正确的。)
git fetch
,没有其他参数
Git确定您当前的分支(通常通过读取HEAD
,但您当然可以通过Git分支
或Git状态查看它是什么)。然后,它将查找该分支的配置条目,该分支将其命名为remote
。例如,假设您在分支dummy
上,并且.git/config
具有(以及其他条目):
在这种情况下,git-fetch
相当于git-fetch-remote-X
。在这一点之后,这相当于情况2,即:
git fetch remote
(除此之外没有其他参数)
Git这次不会查看您当前的分支。要使用的遥控器是命令行中给定的遥控器。它确实为给定的远程服务器查找配置部分。假设您正在使用remote-X
:在本例中,它将查找:
[remote "remote-X"]
url = ...
如果该部分不存在,或者没有url=
条目,则会出现一个错误:fatal:“remote-X”似乎不是git存储库
。否则,它将给出url,并且git fetch
将尝试连接到该存储库。假设它能连接
通常,至少还有一个配置条目,可能更多,如下所示:
fetch = +refs/heads/*:refs/remotes/remote-X/*
(遥控器的名称在此硬编码)。假设有
接下来,git fetch
询问远程服务器它有哪些引用(大多数情况下是分支和标记,虽然您可以获取所有引用,但大多数人只关心分支和标记)。您可以使用git ls remote-X
自己做同样的事情,它会泄漏出如下内容:
676699a0e0cdfd97521f3524c763222f1c30a094 HEAD
222c4dd303570d096f0346c3cd1dff6ea2c84f83 refs/heads/branch
676699a0e0cdfd97521f3524c763222f1c30a094 refs/heads/master
22b38d1..676699a master -> remote-X/master
HEAD
ref的处理方式并不完全一致(我看到它的行为很奇怪),但通常在这里它会被删除。2根据fetch=
refspec重命名和更新剩余的分支。(如果存在多个fetch=
refspec,则会根据所有这些规范对它们进行重命名和更新。例如,这主要用于将refs/notes/
带过来或在refs/rtags/
下创建自己的“远程标记”名称空间。)
在这种情况下,fetch将带来两个分支branch
和master
所需的任何对象,并根据需要更新(本地)“远程分支”名称refs/remotes/remote-X/branch
和refs/remotes/remote-X/master
。对于每个更新的文件,fetch
打印一行,如下所示:
676699a0e0cdfd97521f3524c763222f1c30a094 HEAD
222c4dd303570d096f0346c3cd1dff6ea2c84f83 refs/heads/branch
676699a0e0cdfd97521f3524c763222f1c30a094 refs/heads/master
22b38d1..676699a master -> remote-X/master
如果fetch=
行丢失,您会得到完全不同的结果。输出将为:
* branch HEAD -> FETCH_HEAD
在本例中,就好像(缺失的)fetch=
行在那里并且包含fetch=HEAD
git fetch remote refspec
(refspec
部分实际上是一个或多个refspec,如下所述)
这与案例2类似,只是这一次,“refspec”是在命令行上提供的,而不是从远程服务器的fetch=
配置条目提供的。但是,这里的获取行为非常不同
在这种情况下,让我们暂停片刻,正确地描述refspec。(refspec也适用于git push
,但是,与git一样,实现细节泄漏,并且在那里的工作方式略有不同。)refspec有一个可选的前导加号(+
),我在这里忽略它;3然后是两部分,用冒号隔开(:
)。两者通常只是一个分支名称,但对于分支名称,您可以(并且fetch=
行可以)拼写出“完整”的ref名称,refs/heads/branch
对于获取操作,左侧的名称是远程设备本身的名称(例如,如gitlsremote
所示)。右侧的名称是要在本地git存储库中存储/更新的名称。作为一种特殊情况,您可以在斜杠后面加一个星号(*
)作为最后一个组件,如refs/heads/*
,在这种情况下,左侧匹配的零件在右侧被替换。因此,refs/heads/*:refs/remotes/remote-X/*
是导致refs/heads/master
(如远程上所示,带有git ls remote
)变为refs/remotes/remote-X/master
(如本地存储库中所示,以较短的形式,位于->
行git fetch
的右侧)
如果您没有输入:
676699a0e0cdfd97521f3524c763222f1c30a094 branch 'master' of ...
222c4dd303570d096f0346c3cd1dff6ea2c84f83 branch 'branch' of ...
676699a0e0cdfd97521f3524c763222f1c30a094 not-for-merge branch ...
f07cf14302eab6ca614612591e55f7340708a61b not-for-merge 'refs/notes/commits' ...
22b38d1..676699a master -> remote-X/master
* branch master -> FETCH_HEAD
* branch branch -> FETCH_HEAD
22b38d1..676699a master -> remote-X/master