290

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

即,如果我跑步git fetch --tags,是否有理由立即直接跑步git fetch

git pull和怎么样git pull --tags?同样的情况?

4

6 回答 6

197

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

仅获取标签:

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

详细说明:

请参阅Michael Haggerty (mhagger)提交 c5a84e9

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

refs/tags/*:refs/tags/*

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

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

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

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

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

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


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

请参阅Paul Tan ( )的提交19d122b, 2015年 5 月 13 日。(由Junio C Hamano 合并——提交 cc77b99中,2015 年 5 月 22 日)pyokagan
gitster

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

由于441ed41 (" git pull --tags": error out with a better message., 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将覆盖任何已配置的 refspec,因此不会有合并候选者。因此引入了错误消息以防止混淆。

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

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


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

请参阅Jeff King ( )的提交 5827a03(2016 年 10 月 13 日) 。(由Junio C Hamano 合并——提交 9fcd144中,2016 年 10 月 26 日)peff
gitster

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) 将不再正确。
    但是,如果这些标签指向与客户端获取的内容断开连接的历史记录,那么它将永远不会自动跟踪,并且这些候选者会在每次获取时影响它。

当配置remote.origin.fetch不是默认配置时 Git 2.21(2019 年 2 月)似乎引入了回归('+refs/heads/*:refs/remotes/origin/*'

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

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

请参阅Masaya Suzuki ( ) 的提交 b7e2d8b(2019 年 9 月 15 日(由Junio C Hamano 合并 -- --提交 1d8b0df中,2019 年 10 月 7 日)draftcode
gitster

fetch:用于oidset保留需要的 OID 以便更快地查找

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

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

于 2013-12-16T10:10:00.723 回答
134

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

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

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

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

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

于 2009-07-30T17:53:00.313 回答
52

我要自己回答这个问题。

我已经确定有区别。“git fetch --tags” 可能会引入所有标签,但不会引入任何新的提交!

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

$ git fetch --tags
$ git fetch

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

于 2009-07-30T05:58:33.633 回答
32

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

--tags选项将 refspec 切换为+refs/tags/*:refs/tags/*. 你可以要求git fetch同时抓住两者。我很确定git fetch && 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/*"

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


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

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

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

  • 从遥控器中获取所有头像和标签,因此请使用 refspecrefs/*:refs/*
  • +在 refspec 之前用非快进覆盖本地分支和标签
  • 如果需要,覆盖当前签出的分支-u
  • 删除远程中不存在的分支和标签-p
  • 并强制确定-f
于 2013-02-18T22:57:52.940 回答
11

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

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

git pull当然,它只不过是一个git fetch <thisrefspec>; git merge. 建议您在跳转到之前习惯于手动进行git fetching 和ing,因为它可以帮助您首先了解正在做什么。git mergegit pullgit pull

话虽如此,这种关系与 with 完全相同git fetchgit pull是 的超集git pull --tags

于 2009-07-30T12:19:33.023 回答
3
git fetch upstream --tags

工作得很好,它只会得到新的标签,不会得到任何其他代码库。

于 2018-01-16T00:21:34.217 回答