编辑于2020年1月,根据Tim Bunce的评论:该行为被认为是一个错误,并在Git 2.20中进行了更改以使其更加合理。以下测试针对旧版本的Git。
更新了一些有趣的信息。我将其放入一个shell脚本中,以便进行简单测试:
mkdir ttwo && cd ttwo && git init && git remote add one file://[path]
(and then I remove
ttwo
after running a test).
因此,每次下面的测试都是在新的空白
ttwo
中运行。我这里使用的是Git 2.10.1,但与2.11相比应该没有显着差异(而与某些Linux发行版仍然附带的Git 1.7相比,肯定存在显着差异...)。
首先,让我们执行
无 refspecs的
git fetch
:
$ git fetch one
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 8 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From file://[path]
* [new branch] master -> one/master
* [new tag] annot -> annot
* [new tag] light -> light
这是使用Git版本2.10.1,在同一台机器上使用
file:///home/...
或
/home/...
,两个存储库都能获取到标签(如有需要可以在之间加入
rm -rf texp2
)。
现在让我们使用单个refspec
master
来运行它。从这里开始,我将省略
remote:
到
From:
的部分,只显示更新的分支和/或标签。
$ git fetch one master
[snip]
* branch master -> FETCH_HEAD
* [new branch] master -> one/master
如果我们使用 master:master
,需要添加 --update-head-ok
,将会发生以下情况:
$ git fetch one --update-head-ok master:master
* [new branch] master -> master
* [new tag] annot -> annot
* [new branch] master -> one/master
* [new tag] light -> light
啊哈,现在我们得到了标签!
如果我们获取master
但将其写入refs/remotes/origin/master
,会发生以下情况:
$ git fetch one master:refs/remotes/origin/master
* [new branch] master -> origin/master
* [new tag] annot -> annot
* [new branch] master -> one/master
* [new tag] light -> light
有一个模式正在出现:我们必须写入一些本地引用
让我们将 master
拉取到 x
,并将 light
拉取到 dark
(我尝试过将 foo
拉取到 bar
,但这不起作用,因为 foo
在存储库中不存在):
$ git fetch one master:x light:dark
* [new branch] master -> x
* [new tag] light -> dark
* [new tag] annot -> annot
* [new tag] light -> light
* [new branch] master -> one/master
现在让我们将
master
拉取到
nothing,这会独立失败,但是将
light
拉取到
dark
:
$ git fetch one master light:dark
* branch master -> FETCH_HEAD
* [new tag] light -> dark
* [new tag] annot -> annot
* [new tag] light -> light
* [new branch] master -> one/master
还有最后一个测试:
$ git fetch one master light
* branch master -> FETCH_HEAD
* tag light -> FETCH_HEAD
* [new branch] master -> one/master
这并没有写入我们的标签,仅写入了FETCH_HEAD
,同时进行了常规的机会主义远程跟踪分支更新。
总的来说,当给出显式的引用规范(refspecs)时,我们必须至少写入一个本地引用。不带引用规范的提取(fetching)可以正常工作,因为它使用配置文件中的默认引用规范以及默认标签。使用一些写入本地引用的引用规范进行提取(fetching)是可以工作的。只写入FETCH_HEAD
的引用规范进行提取则会失败。这似乎是一个错误,但Git代码的意图并不清楚,而且Git的标签更新代码非常复杂。
git fetch --all
吗? - Chandan Raigit fetch --tags one master
和普通的git fetch one
命令都会获取one/master
分支以及light
和annot
标签。然而,git fetch one master
命令不会获取标签 - 我正在尝试理解其中的原因。 - user200783