“ git fetch --tags”是否包括“ git fetch”?


270

一个不错的简单问题-“ git fetch”的功能是否是的严格子集git fetch --tags

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

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


11
从Git 1..9 / 2.0(2014年第一季度)开始,答案将。请参阅下面的答案
VonC

3
对于使用编辑“更正了我的文字”的编辑者-不一定要使用连字符或首字母缩写大写,因此您的编辑在语法上不正确,这就是为什么我拒绝了它。
大卫

Answers:


176

注意:从git 1.9 / 2.0(Q1 2014)开始除了在同一命令行中不带选项的情况下,还将git fetch --tags获取标签。

提交c5a84e9迈克尔·哈格蒂(mhagger)

以前,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(提交的commit 19d122b,2015年5月13日。(由Junio C Hamano合并--cc77b99提交中,2015年5月22日)pyokagan
gitster

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(提交5827a03(2016年10月13日(由Junio C Hamano合并--commit 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. 您需要在服务器端有大量的标记引用,这些标记可以自动跟踪(即,客户端没有)。每一个都会触发对pack目录的重新读取。
  3. 在正常情况下,客户端会自动关注这些标签,并且在进行一次大抓取后,(2)将不再正确。
    但是,如果这些标记指向的历史与客户端获取的内容断开连接,那么它将永远不会自动关注,并且这些候选对象将在每次获取时对其进行影响。

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

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

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

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

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

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

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


git-list中的该线程讨论了修改git fetch <remote> <branch>自动跟踪标签行为的可能性(因为它已经更新了针对原始意图的远程跟踪):public-inbox.org/git/…–
ankostis

@ankostis有趣的是:正如Junio在public-inbox.org/git/…中提到的那样,“回到旧的行为可能是解决此线程中正在讨论的问题的一种选择。” (但他们不会:public-inbox.org/git/…
VonC

Git是否有可能向最终用户暴露更多不必要的复杂性,从而需要语法繁重的命令,使其像黑客一样执行常见的操作?我认为所需的内部知识还不够多。
John Fantastico

1
@JohnFantastico我可以理解这一观点。我之前看过:news.ycombinator.com/item?id=16587496。或hackernoon.com/…(“ Git命令只是对数据存储的泄漏抽象。”)
VonC

1
@Vadorequest谢谢。我已经更新了答案,将继续关注邮件列表:public-inbox.org/git/?q=fetch
VonC

131

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

在其他答案和评论中已经说了大多数,但这是一个简洁的解释:

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

简介:如果您真的想完全保持最新,仅使用访存,则必须同时进行。

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


2
谢谢你的评论。我正在通过高延迟网络在Cygwin中运行git-当两者都不需获取时(大约5秒),它的运行速度是它的两倍。
davidA

哦,哇 git-remote会更好吗?简要地查看源代码,我认为它可能只打一个电话-但我不确定它是否会抓住非分支标签。老实说,我不知道是否曾经在分支上看到过任何标签。从我那里获取的东西,只有等待了这么长时间以致于我错过了维护版本,功能版本以及中止旧版本的维护的唯一方法。
卡斯卡贝尔

我认为问题是'git fetch'只在跟踪分支上获取标签。我们有一个脚本,允许用户选择一个有效的分支,因此默认情况下,个人当前未跟踪许多分支。
davidA

我还没有尝试过git-remote,但是它在我不断增长的待办事项上:)
davidA

7
请注意,git remote update实际上并不能代替git fetchgit fetch --tagsgit remote update尽管会引入新标签,但不会更新已更改的现有标签。仅git fetch --tags将更新现有标签。
larsk's

48

我将自己回答。

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

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

$ git fetch --tags
$ git fetch

真可惜,因为速度慢了两倍。如果只有“ git fetch”可以选择执行其通常的操作引入所有标签。


有趣的是,我没有遇到过这种情况(可能是因为我的存储库在测试时是最新的。)+1
VonC

1
怎么样' git remote update myRemoteRepo':那将获取远程内容标签?
VonC

1
git fetch一直在做,它始终拉下所有新提交新标签。您正在运行什么版本的Git?
添维瑟

4
FTR,'git remote update myRemoteRepo'不能很好地工作-似乎没有做'git fetch && git fetch --tags'的工作,特别是因为后续合并没有效果。
davidA,2009年

1
@TimVisher git fetch不会获取不在分支的提交日志中的标签。jQuery UI例如在release标签上执行此操作。我们执行一个git checkout -b temp-branch,进行发布,添加发布所需的文件,更新版本等,然后git commit -m "1.10.x" ; git tag 1.10.x; git push --tags删除本地temp分支。没有到达该标签的远程分支,git fetch也永远不会下载它。
gnarf

31

这里的一般问题是git fetch将获取+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/*"

而且,如果您想将此版本设置为此仓库的默认设置,则可以在默认获取中添加第二个refspec:

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

这将为此遥控器添加第二fetch =.git/config


我花了一段时间寻找项目处理方式。这就是我想出的。

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

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

  • 从遥控器上抓取所有头部和标签,因此请使用refspec refs/*:refs/*
  • +在refspec之前使用非快进覆盖本地分支和标记
  • 如果需要覆盖当前签出的分支 -u
  • 删除远程中不存在的分支和标签 -p
  • 并确保 -f

这应该是答案。
2014年

+1为“该--tags选项将refspec切换为+refs/tags/*:refs/tags/*”。尽管man git-fetch似乎指定了refspec而不带前导+refs/tags/*:refs/tags/*)。
德米特里·明科夫斯基2014年

remote.origin.fetch默认为 +refs/heads/*:refs/remotes/origin/*,即+版本,不是吗?(这意味着,无论原点/分支现在在本地何处,原点/分支都将被覆盖。)
Robert Siemer

...在撰写本文时,除了其他所有内容以外,最近git --tags都在获取标签。请参阅@VonC的答案。
罗伯特·西默

10

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

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

git pull当然,不过是的包装git fetch <thisrefspec>; git merge。建议您在开始使用之前先习惯于手动操作git fetch,因为这首先可以帮助您了解正在做的事情。git mergegit pullgit pull

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


1
“ git pull是git pull --tags的超集”-但是...'git fetch' 不是 'git fetch --tags'的超集,因此关系并不完全相同...?
大卫

9
刚刚发现了这个问题……好吧,在我看来,这git pull没有获得所有标签,而只有从当前分支头可访问的标签。但是,将git pull --tags获取所有标签,并且显然等效于git fetch --tags
Archimedix

2
git fetch upstream --tags

效果很好,它只会获取新标签,而不会获取任何其他代码库。


1
upstream通常称为origin。我认为upstream是GitHub使用的名称。无论如何,要使用的名称都是由表示的名称git remote
Fabio说恢复Monica
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.