这些`git fetch`语法有什么区别?

时间:2014-10-14 00:19:33

标签: git syntax fetch

我已经克隆了一个存储库(git clone --bare),显然git fetch没有更新它,但git fetch origin master:master确实存在。我不明白这些语法之间的所有细微差别:

  • git fetch
  • git fetch origin
  • git fetch origin master
  • git fetch origin master:master

origin是我唯一的遥控器,master是我唯一的分支机构,帮助说:

  

如果未指定遥控器,默认情况下将使用原点遥控器

那么为什么这四行不一样呢?

编辑:这三个第一个命令似乎是在一个名为FEATCH_HEAD的临时分支中获取的。但由于我使用的是裸克隆,因此我无法使用git merge来获取获取的结果。

Edit2:从@ torek的回答中,我做了一个小测试并且差异了--bare和--mirror克隆目录。结果如下:

diff -ru mesa.bare.git/config mesa.mirror.git/config
--- mesa.bare.git/config    2014-10-14 20:01:42.812226509 -0400
+++ mesa.mirror.git/config  2014-10-14 20:00:53.994985222 -0400
@@ -4,3 +4,5 @@
    bare = true
 [remote "origin"]
    url = git://anongit.freedesktop.org/mesa/mesa
+   fetch = +refs/*:refs/*
+   mirror = true
Only in mesa.bare.git/objects/pack: pack-17005b7e1020d291eb86d778a174ecf0d60d92a9.idx
Only in mesa.bare.git/objects/pack: pack-17005b7e1020d291eb86d778a174ecf0d60d92a9.pack
Only in mesa.mirror.git/objects/pack: pack-c08b44b7f290ef0bc9abe3a0b974695c85a69342.idx
Only in mesa.mirror.git/objects/pack: pack-c08b44b7f290ef0bc9abe3a0b974695c85a69342.pack

谢谢!

1 个答案:

答案 0 :(得分:7)

Andrew C's comment包含密钥,但我会稍微阐述一下:

  • git fetch,没有其他参数,通过查看当前分支选择远程名称,或使用origin(有关详细信息,请参阅文档)。选择了一个遥控器后,它将继续进行下一个表格。

  • git fetch remote,再次没有其他参数,使用给定的遥控器,并提取该遥控器的fetch =行以获得一组" refspecs"。然后类似于最后一个案例。

  • git fetch remote refspec使用给定的远程和给定的refspec(您可以在此处给出多个refspec)来选择要更新的引用。

一旦git fetch具有远程或URL给定的远程名称,它将提取url =行以获取URL - 它与远程服务器上的其他git命令联系并要求它们所有远程存储库引用的列表(分支,标记和其他引用,全部在refs/*名称空间中,HEAD的特殊添加,也可以获得但不是通常用于此处 - 它用于初始克隆步骤。)

对于这样获得的每个引用,git fetch会看到您是否要求它引用该引用,如果是,请求git在您的存储库中使用的名称。

同样,名称​​ available 是从遥控器获得的。名称​​想要是从您的refspecs获得的,它们将在您的存储库中提供的名称也可以从您的refspecs中获得。

a:b形式的refspec表示"参考a,但在本地称为b。"

缺少b部分的refspec意味着"参考a,但将其放入特殊的FETCH_HEAD文件中。" (FETCH_HEAD然后变得像普通引用,例如MERGE_HEADORIG_HEAD等等,除了它有一些额外的文本写入pull脚本,所以它有时只会以您期望的方式运作。)

refspec可能包含通配符:refs/heads/*表示"取所有分支" (根据定义,分支是以refs/heads/开头的引用)。通常,git配置中的fetch =行显示为refs/heads/*:refs/remotes/origin/* 1 与以前一样,这意味着重命名匹配的分支,右侧的*扩展为无论结肠左侧的*匹配。因此,这将所有分支结束,但将它们重命名为origin/master等。这通常是你想要一个非--bare存储库。

有时候,这也是--bare存储库所需要的,有时它不是。特别是,有时你想要一个"镜像"存储库,这是一个简单的奴隶复制其他存储库的裸克隆。要将普通的裸存储库更改为这样的镜像,您只需修改fetch =行:而不是refs/heads/*:refs/remotes/origin/*该行应该是fetch = refs/heads/*:refs/heads/*。实际上,您可能希望将{em>所有(标记甚至注释)与fetch = refs/*:refs/*结合起来。当然,无论你真的想要这个,你都可以自己决定。

请注意,这很常见,git clone有一个标记可以自动设置它:使用--mirror进行克隆,然后使用修改后的fetch =行获得裸克隆。


1 实际上该行读取+refs/heads/*:refs/remotes/origin/*,即还有一个前导+字符。此加号设置"强制标记",就像您使用git fetch --force一样,用于特定的参考更新。这与此处的拼写问题并不特别相关,但我要注意,通常您需要对此处列出的远程分支进行强制更新,也需要强制更新纯镜像存储库。

如果你正在镜像标签,你可能希望那些做强制更新。当然,理想情况下,标签永远不会改变(也不会被删除),所以在理想的世界中,这无关紧要,但在现实世界中,它们有时会改变或被删除。

要处理参考删除,您必须告诉git fetch --prune(或类似地,将--prune提供给git remote update)。 refspecs中没有自动修剪的语法(虽然这是合理的,我还没有看到任何提议)。