【问题标题】:Why is git fetch not fetching any tags?为什么 git fetch 不获取任何标签?
【发布时间】:2017-06-08 09:26:27
【问题描述】:

我创建了一个沙箱 git 存储库,其中包含一些提交和几个标签,一个是轻量级的,一个是带注释的:

> mkdir one; cd one; git init

> touch a.txt; git add a.txt; git commit -m"a.txt"

> touch b.txt; git add b.txt; git commit -m"b.txt"
> git tag light

> touch c.txt; git add c.txt; git commit -m"c.txt"
> git tag -a annot -m"annot"

我现在创建第二个存储库并从第一个获取:

> mkdir two; cd two; git init

> git remote add one <...>/one
> git fetch one master
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 9 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
From <...>/one
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> one/master

为什么两个标签都没有被提取?我预计他们会是,基于the documentation for git fetch

默认情况下,任何指向正在获取的历史的标签也会被获取;效果是获取指向您感兴趣的分支的标签。

【问题讨论】:

  • 你试过git fetch --all
  • 我几乎可以肯定 Git 的标签处理多年来发生了显着变化,所以:您运行的是哪个 Git 版本? (而且,如果这是在两台不同的机器上,你使用的是什么 URL 方案,http:// vs git:// vs ssh://,并给出两台机器的 Git 版本......)
  • @crai - git fetch --tags one master 和普通 git fetch one 都获取 one/master 分支以及 lightannot 标签。但是,git fetch one master 没有获取标签 - 我试图了解原因。
  • @torek - 我使用的是最新的 git 版本,2.11.0。两个存储库都在同一台机器上,使用file:// URL 方案。

标签: git tags git-fetch


【解决方案1】:

编辑,2020 年 1 月,Tim Bunce's comment:该行为被认为是一个错误,并在 Git 2.20 中进行了更改,使其更加合理。以下测试适用于较旧版本的 Git。


更新了新的有趣的信息位。为了方便测试,我把它放到了一个 shell 脚本中:

mkdir ttwo && cd ttwo && git init && git remote add one file://[path]

(然后我在运行测试后删除ttwo)。

因此,下面的每个测试都在新的空ttwo 中运行。我在这里也使用 Git 2.10.1,但与 2.11 应该没有显着差异(虽然与 Git 1.7 相比肯定存在显着差异,Git 1.7 仍在某些 Linux 发行版中提供......)。

首先,让我们 git fetch 使用 no refspecs:

$ 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

出现了一种模式:我们必须写入一些本地 ref(s)

让我们获取masterxlightdark(我尝试将foobar 但这不起作用,因为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,加上通常的机会主义远程跟踪分支更新。

底线似乎是,当给出明确的参考规范时,我们必须写至少一个本地参考。使用 no refspecs 获取有效,因为它使用了配置文件中的默认 refspecs 以及默认标记。使用一些写入本地 ref 的 refspec 进行获取。使用仅写入 FETCH_HEAD 的某些 refspec 获取失败。这似乎是一个错误,但不清楚 Git 中代码的意图是什么,而且 Git 的标签更新代码非常曲折。

【讨论】:

  • 像这样使用git fetch one 会为我获取one/master 分支以及lightannot 标签。但是,我期待 git fetch one master 也能获取标签 - 我试图理解为什么它没有。
  • 非常感谢您进行所有这些测试!根据证据,似乎确实要获得标签,至少一个明确的 refspec 必须有一个明确的目的地。因此,获取master 以及相关标签的方法看起来是git fetch one master:refs/remotes/one/master。这是您推荐用来代替git fetch one master 的命令吗?
  • @user200783:是的,假设是标准的(非镜像样式,没有其他有趣的业务与配置中的fetch refspec)配置。如果您想在脚本中更加偏执,您可以运行 git config --get-all remote.one.fetch 并解析结果输出。我可能只会git fetch one master:refs/remotes/one/master。 :-)
  • 似乎是行为错误或文档错误,是的。没有提到 default-tags 被仅远程的 refspec 击败...
  • 仅供参考,在 git 2.20 中的行为发生了变化,每 git-scm.com/docs/git-fetch“自 Git 版本 2.20 起,获取更新 refs/tags/* 的工作方式与推送时相同。即,任何更新都将被拒绝而没有 + in refspec(或 --force)。”
【解决方案2】:

不是一个真实的答案,但我是通过 Google 搜索到达这里的,因为 git fetch 没有拉我的标签(通常会这样做)。因此,这适用于在同一条船上偶然发现这个措辞非常相似的问题的任何其他人。

我可以手动拉出标签:git fetch --tags

【讨论】:

  • 这个答案有帮助。我本来希望git fetch --all 也能获得标签,但事实并非如此。这做到了。谢谢!
  • 这应该是公认的答案
  • 这里有同样的问题。奇怪的是,git fetch 并不像往常那样总是获取所有标签。
猜你喜欢
  • 2017-06-06
  • 2020-09-03
  • 2015-09-19
  • 2021-03-20
  • 2015-08-15
  • 2016-10-06
  • 2013-05-25
  • 2014-03-31
  • 2019-11-15
相关资源
最近更新 更多