一个很好的简单的问题——“git fetch”函数是git fetch --tags的严格子集吗?
git fetch --tags
例如,如果我运行git fetch --tags,是否有理由在之后立即直接运行git fetch ?
git fetch
那么git pull和git pull --tags呢?同样的情况?
git pull
git pull --tags
我自己来回答这个问题。
我认为这是有区别的。"git fetch——tags"可能会带来所有的标签,但它不会带来任何新的提交!
事实证明,必须这样做才能完全“更新”,即复制一个“git pull”而不合并:
$ git fetch --tags $ git fetch
这很遗憾,因为它要慢一倍。如果“git fetch”有一个选项来做它通常做的而且带来所有的标签。
在大多数情况下,git fetch应该做你想做的事情,即“从远程存储库获取任何新内容,并将其放在本地副本中,而不合并到本地分支”。git fetch --tags就是这样做的,除了新标签之外,它没有得到任何东西。
从这个意义上说,git fetch --tags绝不是git fetch的超集。事实恰恰相反。
当然,git pull只是git fetch <thisrefspec>; git merge的包装器。建议你在跳转到git pull之前习惯手动git fetching和git mergeing,因为这可以帮助你首先理解git pull在做什么。
git fetch <thisrefspec>; git merge
git merge
话虽如此,其关系与git fetch完全相同。git pull是git pull --tags的超集。
注意:这个答案只对git v1.8及更老版本有效。
大多数问题已经在其他的回答和评论中提到了,但这里有一个简明的解释:
总结:如果你真的想要完全更新,只使用fetch,你必须两者都做。
它也不是“两倍慢”,除非你指的是在命令行上输入,在这种情况下,别名可以解决你的问题。发出这两个请求基本上没有开销,因为它们请求的是不同的信息。
这里的一般问题是git fetch将获取+refs/heads/*:refs/remotes/$remote/*。如果这些提交中的任何一个有标记,这些标记也将被获取。但是,如果远程上的任何分支都无法到达标记,则不会获取它们。
+refs/heads/*:refs/remotes/$remote/*
--tags选项将refspec转换为+refs/tags/*:refs/tags/*。你可以让git fetch抓取两个。我非常确定要执行git fetch && git fetch -t,您将使用以下命令:
--tags
+refs/tags/*:refs/tags/*
git fetch && git fetch -t
git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"
如果你想让它成为这个repo的默认值,你可以添加第二个refspec到默认的取回:
git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"
这将在这个遥控器的.git/config中添加第二个fetch =行。
.git/config
fetch =
我花了一段时间寻找处理这个项目的方法。这是我想到的。
git fetch -fup origin "+refs/*:refs/*"
就我而言,我想要这些功能
refs/*:refs/*
+
-u
-p
-f
注意:从git 1.9/2.0(2014年第一季度)开始,git fetch --tags获取标记除了,这些标记是由相同的命令行获取的,没有选项。
只获取标签:
git fetch <remote> 'refs/tags/*:refs/tags/*'
详细:
参见提交c5a84e9 by 迈克尔·哈格蒂(mhagger):
以前,fetch's "--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)
以前,fetch's "--tags"选项被认为等同于指定refspec
refs/tags/*:refs/tags/*
在命令行; 特别是,它导致remote.<name>.refspec配置被忽略 但是,在不获取其他引用的情况下获取标签是不太有用的,而能够获取标签除了其他引用是非常有用的。 因此,将该选项的语义改为后者
remote.<name>.refspec
如果用户想获取只有标记,则仍然可以指定显式refspec:
fetch --tags
Documentation/fetch-options.txt
请求从远程除了要获取的其他东西获取所有标签。
因为Git 2.5 (Q2 2015) git pull --tags更加健壮:
参见提交19 d122b by Paul Tan (pyokagan), 2015年5月13日。 (由Junio C Hamano—gitster—在提交cc77b99中合并,22 May 2015)
pyokagan
gitster
pull:在没有合并候选的情况下删除--tags错误
pull
由于441年ed41 ("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: fetch tags in addition to 其他东西,2013-10-30,Git 1.9.0+), git fetch --tags将获取额外的标签 到任何配置的refspecs。 因此,如果出现任何没有合并候选的情况,这并不是因为设置了--tags。因此,这个特殊的错误信息现在是不相关的 为防止混淆,请删除此错误消息。
由于441年ed41 ("git pull --tags":错误输出了一个更好的消息。, 2007-12-28, Git 1.5.4+), git pull --tags将打印不同的错误消息 git-fetch没有返回任何合并候选项:
git-fetch
It doesn't make sense to pull all tags; you probably meant: git fetch --tags
git-fetch --tags
然而,由于c5a84e9 (fetch --tags: fetch tags in addition to 其他东西,2013-10-30,Git 1.9.0+), git fetch --tags将获取额外的标签 到任何配置的refspecs。 因此,如果出现任何没有合并候选的情况,这并不是因为设置了--tags。因此,这个特殊的错误信息现在是不相关的
为防止混淆,请删除此错误消息。
在Git 2.11+(2016年Q4)中,git fetch更快。
参见提交5827年a03 (13 Oct 2016) by 杰夫·金(peff)。 (由Junio C Hamano—gitster— in 提交9 fcd144合并,2016年10月26日)
peff
fetch:使用“快速”;has_sha1_file用于标签跟随
fetch
has_sha1_file
当从一个具有许多与我们所跟踪的分支无关的标记的远程获取时,我们曾经在检查标记所指向的对象(我们不打算获取!)是否存在于我们的存储库中时浪费了太多的周期。 这个补丁教fetch使用HAS_SHA1_QUICK来牺牲 准确的速度,在这种情况下,我们可能会用一个 同时重新打包。< / p > 下面是包含的perf脚本的结果,它设置了类似于上面描述的情况: Test HEAD^ HEAD ---------------------------------------------------------- 5550.4: fetch 11.21(10.42+0.78) 0.08(0.04+0.02) -99.3%
当从一个具有许多与我们所跟踪的分支无关的标记的远程获取时,我们曾经在检查标记所指向的对象(我们不打算获取!)是否存在于我们的存储库中时浪费了太多的周期。
下面是包含的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)将不再为真。 但是如果这些标签指向的历史记录与客户端获取的内容不连接,那么它将永远不会自动跟踪,并且这些候选标签将在每次获取时影响它
reprepare_packed_git()
Git 2.21(2019年2月)似乎引入了一个回归,当config remote.origin.fetch是不是是默认值 ('+refs/heads/*:refs/remotes/origin/*')
remote.origin.fetch
'+refs/heads/*:refs/remotes/origin/*'
fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed
Git 2.24(2019年Q4)增加了另一项优化。
参见提交b7e2d8b (15 Sep 2019) by 铃木雅哉(draftcode)。 (由Junio C Hamano—gitster—在提交1 d8b0df中合并,07 Oct 2019)
draftcode
fetch:使用oidset保存想要的oid,以便更快地查找
oidset
在git fetch期间,客户端检查所发布的标签的OID是否已经在获取请求的想要的OID集中。 这种检查是在线性扫描中完成的。 对于一个有很多引用的存储库,重复这个扫描需要15分钟以上 为了加快这个过程,为其他引用的oid创建oid_set。
为了加快这个过程,为其他引用的oid创建oid_set。
oid_set
git fetch upstream --tags
工作得很好,它只会得到新的标记,而不会得到任何其他代码基。