【问题标题】:Does "git fetch --tags" include "git fetch"?“git fetch --tags”是否包括“git fetch”?
【发布时间】:2023-03-04 14:21:02
【问题描述】:

一个很好很简单的问题——“git fetch”的功能是git fetch --tags的严格子集吗?

即如果我运行git fetch --tags,是否有理由立即运行git fetch

git pullgit pull --tags 呢?同样的情况?

【问题讨论】:

  • 启动 Git 1..9/2.0(2014 年第一季度),答案将是。见my answer below
  • 致通过编辑“更正我的文本”的编辑 - 连字符或首字母缩略词后不一定大写,因此您的编辑在语法上不正确,这就是我拒绝它的原因。

标签: git pull git-tag git-fetch


【解决方案1】:

注意:以git 1.9/2.0 (Q1 2014) 开头,git fetch --tags 获取标签除了没有选项的同一命令行获取的内容。

仅获取标签:

git fetch <remote> 'refs/tags/*:refs/tags/*'

详细说明:

commit c5a84e9Michael Haggerty (mhagger)

以前,fetch 的“--tags”选项被认为等同于指定 refspec

refs/tags/*:refs/tags/*

在命令行上; 特别是,它导致remote.&lt;name&gt;.refspec 配置被忽略。

但是在不获取其他引用的情况下获取标签并不是很有用,而 能够获取标签以及其他引用非常有用。 所以改变这个选项的语义来做后者。

如果用户想获取 only 标签,那么仍然可以指定显式 refspec:

git fetch <remote> 'refs/tags/*:refs/tags/*'

请注意,1.8.0.3 之前的文档对“fetch --tags”行为的这一方面不明确。
Commit f0cb2f1 (2012-12-14) fetch --tags 使文档与旧行为匹配。
此提交更改文档以匹配新行为(请参阅Documentation/fetch-options.txt)。

请求从远程获取所有标签以及正在获取的任何其他标签


由于 Git 2.5(2015 年第二季度)git pull --tags 更加强大:

参见commit 19d122bPaul Tan (pyokagan),2015 年 5 月 13 日。
(由 Junio C Hamano -- gitster -- 合并,commit cc77b99,2015 年 5 月 22 日)

pull:在没有合并候选的情况下删除 --tags 错误

由于441ed41 ("git pull --tags": 错误输出更好的消息。, 2007-12-28,Git 1.5.4+),git pull --tags 将打印不同的错误消息,如果 git-fetch 没有返回任何合并候选者:

It doesn't make sense to pull all tags; you probably meant:
      git fetch --tags

这是因为当时git-fetch --tags 会覆盖任何 配置了 refspecs,因此不会有合并候选者。因此引入了错误消息以防止混淆。

但是,由于c5a84e9fetch --tags:获取标签除了 其他东西,2013-10-30,Git 1.9.0+),git fetch --tags 会另外获取标签 到任何已配置的 refspecs。
因此,如果出现任何没有合并候选者的情况,并不是因为设置了--tags。因此,这个特殊的错误信息现在已经无关紧要了。

为防止混淆,请删除此错误消息。


使用 Git 2.11+(2016 年第四季度)git fetch 更快。

参见Jeff King (peff)commit 5827a03(2016 年 10 月 13 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit 9fcd144,2016 年 10 月 26 日)

fetch:使用“快速”has_sha1_file 进行标签跟踪

当从具有许多与我们所遵循的分支无关的标签的远程获取时,我们在检查标签指向的对象(我们不会获取!)是否存在时浪费了太多的周期在我们的存储库中太小心了。

这个补丁教 fetch 使用 HAS_SHA1_QUICK 牺牲 速度的准确性,在我们可能对 同时重新包装。

以下是包含的 perf 脚本的结果,该脚本设置了与上述类似的情况:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

这仅适用于以下情况:

  1. 您在客户端有很多包使 reprepare_packed_git() 变得昂贵(最昂贵的部分是在未排序的列表中查找重复项,目前是二次的)。
  2. 您需要在服务器端有大量标签引用作为自动跟随的候选对象(即客户端没有)。 每一个都会触发对包目录的重新读取。
  3. 在正常情况下,客户端会自动跟踪这些标签,并且在一次大抓取之后,(2) 将不再正确。
    但是,如果这些标签指向的历史与客户端获取的内容断开连接,那么它将永远不会自动跟踪,并且这些候选者会在每次获取时影响它。

Git 2.21(2019 年 2 月)似乎在 config remote.origin.fetch is not the default one ('+refs/heads/*:refs/remotes/origin/*') 时引入了回归

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed

Git 2.24(2019 年第四季度)增加了另一项优化。

参见Masaya Suzuki (draftcode)commit b7e2d8b(2019 年 9 月 15 日)。
(由 Junio C Hamano -- gitster -- 合并到 commit 1d8b0df,2019 年 10 月 7 日)

fetch:使用 oidset 保留需要的 OID 以加快查找速度

git fetch 期间,客户端检查广告标签的 OID 是否已在获取请求的所需 OID 集中。
此检查是在线性扫描中完成的。
对于具有大量引用的存储库,重复此扫描需要 15 分钟以上。

为了加快速度,请为其他裁判的 OID 创建一个 oid_set

【讨论】:

  • git-list 中的这个线程讨论了将git fetch &lt;remote&gt; &lt;branch&gt; 的行为修改为自动关注标签的可能性(因为它已经更新了远程跟踪而不是最初的意图):public-inbox.org/git/…
  • @ankostis 有趣:正如 Junio 在public-inbox.org/git/… 中提到的那样,“回到旧的行为可能是解决此线程中正在讨论的问题的一种选择。” (但他们不会:public-inbox.org/git/…
  • Git 是否有可能向最终用户暴露更多不必要的复杂性,需要语法繁重的命令到类似于 hack 的程度才能执行常见操作?我认为所需的内部知识还不够。
  • @JohnFantastico 我可以理解这种观点。我以前见过:news.ycombinator.com/item?id=16587496。或hackernoon.com/…(“Git 命令只是对数据存储的泄漏抽象。”)
  • @Vadorequest 谢谢。我已经更新了答案,并会留意邮件列表:public-inbox.org/git/?q=fetch
【解决方案2】:

注意:此答案仅对 git v1.8 及更早版本有效。

其他答案和cmets中已经说了大部分,但这里有一个简明的解释:

  • git fetch 获取所有分支头(或所有由 remote.fetch 配置选项指定的)、它们所需的所有提交以及可从这些分支访问的所有标记。在大多数情况下,所有标签都可以通过这种方式访问​​。
  • git fetch --tags 获取所有标签,以及它们所需的所有提交。它不会更新分支头,即使它们可以从获取的标签中访问。

总结:如果你真的想完全保持最新,只使用 fetch,你必须同时做。

它也不是“两倍慢”,除非您是指在命令行上键入,在这种情况下别名可以解决您的问题。发出这两个请求基本上没有开销,因为它们要求的信息不同。

【讨论】:

  • 感谢您的评论。我在 Cygwin 中通过高延迟网络运行 git - 当两者都没有可获取的内容时(大约 5 秒),它的速度要慢两倍。
  • 哦,哇。 git-remote 工作得更好吗?简要查看源代码,我认为它可能只打一个电话 - 但我不完全确定它是否会抓取非分支标签。老实说,我不知道我是否见过任何不在分支上的标签。对于我从中提取的东西,如果我等待太久以致错过了维护版本、功能版本以及旧版本的维护中止,唯一的可能发生的情况。
  • 我认为问题在于 'git fetch' 只获取 tracked 分支上的标签。我们有一个脚本允许用户选择一个工作分支,所以默认情况下有很多分支当前没有被个人跟踪。
  • 我还没有尝试过 git-remote,但它在我不断增长的待办事项清单上 :)
  • 请注意,git remote update 实际上并不是git fetchgit fetch --tags 的替代品。 git remote update 不会更新已更改的现有标签,但会引入新标签。只有git fetch --tags 会更新已经存在的标签。
【解决方案3】:

我自己来回答。

我已经确定存在差异。 "git fetch --tags" 可能会引入所有标签,但不会引入任何新的提交!

事实证明,必须这样做才能完全“最新”,即在没有合并的情况下复制“git pull”:

$ git fetch --tags
$ git fetch

这很遗憾,因为它的速度是原来的两倍。如果只有“git fetch”可以选择做它通常会做的事情引入所有标签。

【讨论】:

  • 有趣,我没有经历过(可能是因为我的 repo 在我测试时是最新的。)+1
  • 'git remote update myRemoteRepo'怎么样:它会获取远程内容标签吗?
  • 我一直在做git fetch,它会不断地拉下任何新的提交任何新的标签。你运行的是什么版本的 Git?
  • FTR, 'git remote update myRemoteRepo' 不能正常工作 - 似乎没有像 'git fetch && git fetch --tags' 那样做,尤其是在后续合并没有效果的情况下。跨度>
  • @TimFisher git fetch 不会抓取不在分支提交日志中的标签。例如,jQuery UI 在发布标签上执行此操作。我们做一个git checkout -b temp-branch,做我们的发布,添加发布所需的文件,更新版本等,然后git commit -m "1.10.x" ; git tag 1.10.x; git push --tags,然后我们删除我们的本地临时分支。没有到达该标签的远程分支,git fetch 永远不会下载它。
【解决方案4】:

这里的一般问题是git fetch 将获取+refs/heads/*:refs/remotes/$remote/*。如果这些提交中的任何一个有标签,这些标签也将被获取。但是,如果远程上的任何分支都无法访问标签,则不会获取它们。

--tags 选项将 refspec 切换为 +refs/tags/*:refs/tags/*。您可以要求git fetch 获取两者。我很确定只做一个git fetch &amp;&amp; git fetch -t 你会使用以下命令:

git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"

如果你想让它成为这个 repo 的默认值,你可以在默认 fetch 中添加第二个 refspec:

git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"

这将在此遥控器的.git/config 中添加第二个fetch = 行。


我花了一段时间为一个项目寻找处理这个问题的方法。这就是我想出的。

git fetch -fup origin "+refs/*:refs/*"

就我而言,我想要这些功能

  • 从远程获取所有磁头和标签,因此使用 refspec refs/*:refs/*
  • 在 refspec 之前用非快进 + 覆盖本地分支和标签
  • 如果需要,覆盖当前签出的分支-u
  • 删除远程-p中不存在的分支和标签
  • 并强制确定-f

【讨论】:

  • 这应该是答案。
  • +1 表示“--tags 选项将 refspec 切换为 +refs/tags/*:refs/tags/*”。尽管man git-fetch 似乎指定了没有前导+ (refs/tags/*:refs/tags/*) 的引用规范。
  • remote.origin.fetch 默认为+refs/heads/*:refs/remotes/origin/*,即+ 版本,不是吗? (这意味着,无论原点/分支现在在本地哪里,原点/分支都将被覆盖。)
  • ...在撰写本文时,最近的git --tags 正在获取标签除了之外的所有内容。请参阅@VonC 的答案。
【解决方案5】:

在大多数情况下,git fetch 应该做您想做的事,即“从远程存储库中获取任何新内容并将其放入本地副本而不合并到本地分支”。 git fetch --tags 正是这样做的,只是它除了新标签之外什么都没有。

从这个意义上说,git fetch --tags 绝不是git fetch 的超集。事实上恰恰相反。

git pull 当然,不过是git fetch &lt;thisrefspec&gt;; git merge 的包装器。建议您在跳转到 git pull 之前习惯手动操作 git fetching 和 git mergeing,因为它可以帮助您了解 git pull 首先在做什么。

话虽如此,关系与git fetch 完全相同。 git pullgit pull --tags 的超集。

【讨论】:

  • "git pull 是 git pull --tags 的超集" - 但是... 'git fetch' 不是 'git fetch --tags' 的超集所以关系不完全一样...?
  • 刚发现这个问题...好吧,在我看来git pull 确实 not 获得 all 标签,但只有那些可从现任分公司负责人。然而,git pull --tags 获取所有标签,显然等同于git fetch --tags
【解决方案6】:
git fetch upstream --tags

工作正常,它只会获取新标签,不会获取任何其他代码库。

【讨论】:

  • upstream 通常称为origin。我认为upstream 是 GitHub 使用的名称。无论如何,要使用的名称是git remote 显示的名称。
猜你喜欢
  • 2017-06-02
  • 2016-08-06
  • 2014-02-27
  • 1970-01-01
  • 2014-03-31
  • 2012-11-07
  • 2013-02-21
  • 2022-06-14
相关资源
最近更新 更多