一个简单明了的问题 - “git fetch”的功能是git fetch --tags
的严格子集吗?
即。如果我运行git fetch --tags
,是否有理由立即立即运行git fetch
?
git pull
和git pull --tags
怎么样?同样的情况?
答案 0 :(得分:156)
注意:从git 1.9/2.0 (Q1 2014)开始,git fetch --tags
除之外还提取标记在没有选项的情况下由同一命令行提取的内容。
commit c5a84e9见Michael Haggerty (mhagger):
以前,fetch的“
--tags
”选项被认为等同于指定refspecrefs/tags/*:refs/tags/*
在命令行上; 特别是,它导致
remote.<name>.refspec
配置被忽略。但是在没有获取其他引用的情况下获取标记并不是非常有用,而 除了其他引用之外还能够获取标记非常有用。登记/> 因此,请更改此选项的语义以执行后者。
如果用户想要仅提取 标签,那么仍然可以指定显式的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年第2季度)git pull --tags
更强大:
2015年5月13日commit 19d122b旁边的Paul Tan (pyokagan
)
(Junio C Hamano -- gitster
--在2015年5月22日commit cc77b99合并)
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,因此没有合并候选人。因此引入了错误消息以防止混淆。但是,由于c5a84e9(
fetch --tags
:提取标记以及 其他的东西,2013-10-30,Git 1.9.0+),git fetch --tags
还会获取标签 任何配置的refspecs 因此,如果没有合并候选人情况发生,那不是因为设置了--tags
。因此,此特殊错误消息现在无关紧要。为防止混淆,请删除此错误消息。
使用Git 2.11 +(2016年第4季度)git fetch
更快。
commit 5827a03见Jeff King (peff
)(2016年10月13日)
(Junio C Hamano -- gitster
--于2016年10月26日commit 9fcd144合并)
fetch
:使用“quick”has_sha1_file
标记当从具有许多与我们正在关注的分支无关的标记的远程获取时,我们常常在检查标记所指向的对象(我们不会获取!)时是否浪费了太多周期在我们的存储库中太小心了。
这个补丁教授fetch使用HAS_SHA1_QUICK来牺牲 对于速度的准确性,如果我们可能与a充满活力 同时重新包装。
以下是包含的perf脚本的结果,该脚本设置了与上述情况类似的情况:
Test HEAD^ HEAD
----------------------------------------------------------
5550.4: fetch 11.21(10.42+0.78) 0.08(0.04+0.02) -99.3%
这仅适用于以下情况:
- 您在客户端有很多包使
reprepare_packed_git()
成本高昂(最昂贵的部分是在未排序的列表中查找重复项,目前是二次的)。- 您需要服务器端的大量标记引用,这些引用是自动跟踪的候选者(即客户端没有)。 每一个都会触发重新读取包目录。
- 在正常情况下,客户端会自动关注这些标记,在一次大量提取后,(2)将不再为真。
醇>
但是,如果这些标记指向与客户端提取的内容不相关的历史记录,那么它将永远不会自动跟随,并且这些候选项将在每次提取时影响它。
remote.origin.fetch
is not the default one('+refs/heads/*:refs/remotes/origin/*'
)时,Git 2.21(2019年2月)似乎引入了回归
fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed
答案 1 :(得分:130)
注意:此答案仅适用于git v1.8及更早版本。
其他答案和评论中都提到了大部分内容,但这里有一个简明的解释:
git fetch
获取所有分支头(或由remote.fetch配置选项指定的所有分支头),它们所需的所有提交,以及可从这些分支到达的所有标记。在大多数情况下,所有标签都可以通过这种方式访问。git fetch --tags
获取所有标记,以及它们所需的所有提交。它将不更新分支头,即使它们可以从提取的标签中访问。总结:如果你真的想要完全更新,只使用fetch,你必须同时做到这两点。
除非你在命令行上输入,否则它也不会“慢两倍”,在这种情况下,别名可以解决你的问题。这两个请求基本上没有开销,因为他们要求提供不同的信息。
答案 2 :(得分:48)
我自己会回答这个问题。
我已经确定存在差异。 “git fetch --tags”可能会引入所有标记,但它不会带来任何新的提交!
原则上必须做到这一点才能完全“更新”,即在没有合并的情况下复制“git pull”:
$ git fetch --tags
$ git fetch
这是一种耻辱,因为它的速度慢了两倍。如果只有“git fetch”可以选择执行和带来的所有标记。
答案 3 :(得分: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/*"
如果你想让它成为这个repo的默认值,你可以在默认的fetch中添加第二个refspec:
git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"
这将为此遥控器的fetch =
添加第二条.git/config
行。
我花了一段时间寻找处理项目的方法。这就是我想出来的。
git fetch -fup origin "+refs/*:refs/*"
在我的情况下,我想要这些功能
refs/*:refs/*
+
覆盖本地分支和代码
-u
-p
-f
答案 4 :(得分:10)
在大多数情况下,git fetch
应该执行您想要的操作,即“从远程存储库中获取任何新内容并将其放入本地副本,而不必合并到本地分支”。 git fetch --tags
正是这样做的,除了除了新标签之外它什么都没有。
从这个意义上讲,git fetch --tags
绝不是git fetch
的超集。事实上恰恰相反。
git pull
只不过是git fetch <thisrefspec>; git merge
的包装。建议您在跳转到git fetch
之前习惯于进行手动git merge
和git pull
,因为它可以帮助您了解git pull
在第一次做什么的地方。
话虽如此,这种关系与git fetch
完全相同。 git pull
是git pull --tags
的超集。
答案 5 :(得分:1)
git fetch upstream --tags
工作正常,它只会获得新标签,不会获得任何其他代码库。