【问题标题】:Having a hard time understanding git-fetch很难理解 git-fetch
【发布时间】:2010-11-07 09:58:57
【问题描述】:

我很难理解 git-fetch 的细微差别。我知道执行fetch 会将远程引用获取到本地跟踪分支。

不过我有几个问题:

  1. 本地跟踪分支可能不存在吗?如果有,会自动创建吗?

  2. 如果我执行fetch 并指定非跟踪分支作为目标会发生什么?

  3. git-fetch 的手册页指定:

    git-fetch <options> <repository> <refspec>
    

如何使用 refspec 将远程 master 中的内容提取到其远程跟踪分支中?我相信如果我当前的 HEAD 在 master 上并且我运行,这可能是可能的

git fetch origin master

但是,我可以使用&lt;+?src:dest&gt; refspec 来实现同样的目的吗?我认为这将有助于我更好地理解这些概念。

还有一个问题:

我的 .git/config 文件有以下行用于获取(仅显示相关行):

fetch = +refs/heads/*:refs/remotes/origin/*

有人可以解释一下这条线的确切含义吗?

【问题讨论】:

  • 自 Git 2.1(2014 年 8 月)以来,还有更多关于 git fetch 的信息。见my answer below

标签: git git-fetch


【解决方案1】:

首先,没有本地跟踪分支的概念,只有远程跟踪分支。所以 origin/masterorigin 存储库中 ma​​ster 的远程跟踪分支。

通常您会执行 git fetch $remote,它会更新所有远程跟踪分支,并在需要时创建新分支。

但是,您也可以指定一个 refspec,但这不会触及您的远程跟踪分支,而是会获取您指定的分支并将其保存在 FETCH_HEAD 上,除非您指定了目的地。一般来说,你不想搞砸这个。

最后,

fetch = +refs/heads/*:refs/remotes/origin/*

这意味着如果你这样做

git fetch origin

它实际上会这样做:

git fetch origin +refs/heads/*:refs/remotes/origin/*

这意味着远程 heads/foobar 将是本地 remotes/origin/foobar,加号表示即使它们不快也会更新-前进。

也许你认为的跟踪分支与 git pull 和合并配置有关。

【讨论】:

  • 当您添加此回复时,我正要开始回答这个问题。我不能说得更好。 +1
  • 您好,felipic,感谢您的回答。它帮助消除了我的许多疑虑。关于远程跟踪分支的一个问题。如果我理解正确,远程跟踪分支存在于我当前的存储库中,旨在跟踪存在于其他(远程)存储库中的代码。如果这是真的,那么说远程跟踪分支就像存在于远程存储库中的实际分支的代理是否合适?
  • 是的,确切地说,它就像一个远程仓库的缓存视图,您可以随意更新。
  • origin/master 是 refs/remotes/origin/master 的简写。
  • @Howiecamp 他们的术语令人困惑。本地分支“master”就是:一个本地分支。他们得到了正确的远程跟踪分支:“origin/master”。文章讲的是 upstream 跟踪分支,但正确的思考方式是反过来:“origin/master”是“master”的上游:它是一个属性“主”分支。不是其他方式:“master”不是“origin/master”的跟踪分支。 felipec.wordpress.com/2013/09/01/…
【解决方案2】:

felipec 拥有answered most of issues in question in his answer

剩下的一些(大部分取自 git fetch 手册页;不幸的是,有些地方有点过时了):

  • 如果 remote-tracking 分支(在某个远程存储库中跟踪某个分支的分支)不存在,则会创建它。

  • 您提取到的分支([+]&lt;src&gt;:&lt;dst&gt; 中的&lt;dst&gt;)不需要驻留在remotes/&lt;remote&gt;/ 命名空间中。例如,对于镜像存储库 (git clone --mirror),refspec 是 1 比 1。过去,在单独的远程布局之前(在 remotes/&lt;remote&gt;/ 远程跟踪引用的命名空间之前)master 分支被提取到名为 原产地。即使目前标签也以镜像方式直接提取到 tags/ 命名空间中。

  • 1234563 &lt;src&gt; 在给定的远程存储库中。如果不是,并且您不使用 git-fetch 的 -f/--force 选项,或者在 refspec 前加上“+”(使用 +&lt;src&gt;:&lt;dst&gt; refspec),则提取将拒绝更新该分支。
  • git fetch origin master 等价于git fetch origin master:,而不是git fetch origin master:master;它将获取的 master 分支(远程 origin)的值存储在 FETCH_HEAD 中,而不是在 master 分支或远程-跟踪remotes/origin/master 分支。后面可以跟git merge FETCH_HEAD。通常不直接使用,但作为一次性拉取的一部分,无需设置远程跟踪分支:git pull &lt;URL&gt; &lt;branch&gt;

  • +refs/heads/*:refs/remotes/origin/* 作为 remote.origin.fetch 配置变量的值意味着获取远程 origin 中的每个分支(refs/heads/ 命名空间中的引用)进入refs/remotes/origin/命名空间中分别命名的远程跟踪分支,例如origin 中的 master 分支(即refs/heads/master ref)将被提取到origin/master 远程跟踪分支(即refs/remotes/origin/master ref) . '+' 前缀意味着即使在非快进的情况下 fetch 也会成功,这意味着当远程分支被重新定位,或重绕(重置为过去的某个状态)或以其他方式修改时。

旁注:您可能希望使用更高级别的git remote 命令来管理远程存储库并获取更新。

【讨论】:

  • 是的,“git remote update”真的很方便,尤其是当你有多个遥控器时。
  • 嗨,Jakub,感谢您的回答。在第 4 点(以“git fetch origin master”开头的段落)中,您说远程存储库将存储在 origin 而不是 remotes/origin/master 中。这是因为该命令翻译成没有目的地的“git fetch origin master:”吗?现在如果我想合并内容,那么我应该与 FETCH_HEADS 合并吗?这是正确的获取方式还是我们应该确保将远程内容提取到 refs/remotes/origin/master 中?
  • @blog.adaptivesoftware.biz:我编辑了答案以试图更好地解释它。当您计划多次从远程获取时,通常最好设置远程跟踪分支(使用“git remote add”); “git pull ”(及其 git-fetch + git-merge 等效项)用于一次性拉取。
  • 我知道这是一篇旧帖子,但我有一个问题。如果 refspec = +refs/heads/master:refs/remotes/origin/mastergit fetch master 不是快进(假设人们在远程仓库中重新设置了 master 分支),那么我的本地 refs/remotes/master ref 将是 重置等于相同的SHA1,还是会发生一些内容合并?
  • @AlexanderBird:最好将问题作为问题提出,而不是在 cmets 中......无论如何,参考将被重置,因为远程端没有人可以要求解决可能的合并冲突 - 屏幕后面没有人。
【解决方案3】:

请注意,Git 的主要维护者现在(Git 2.1,2014 年 8 月)为 git fetch 添加了此解释:
(见commit fcb14b0Junio C Hamano (gitster)

配置的远程跟踪分支

您经常与同一个远程存储库进行交互,方法是定期重复地从中获取。为了跟踪这样一个远程仓库的进度,git fetch 允许你配置remote.&lt;repository&gt;.fetch 配置变量。

通常这样的变量可能如下所示:

[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*

这个配置有两种使用方式:

  • git fetch 运行时没有指定在命令行上获取哪些分支和/或标签,例如git fetch origingit fetch, remote.&lt;repository&gt;.fetch 值用作 refspecs——它们指定要获取哪些 refs 以及要更新哪些本地 refs
    上面的示例将获取存在于origin 中的所有分支(即任何匹配值左侧的引用,refs/heads/*)并更新refs/remotes/origin/* 层次结构中相应的远程跟踪分支。

  • git fetch 使用显式分支和/或标签运行以在命令行上获取时,例如git fetch origin master,在命令行中给出的&lt;refspec&gt;s 确定要获取的内容(例如示例中的master,它是master: 的简写,这反过来意味着“获取'@987654341 @' 分支,但我没有明确说明要从命令行更新哪个远程跟踪分支”),示例命令将获取 'master' 分支。
    remote.&lt;repository&gt;.fetch 值确定更新哪个远程跟踪分支(如果有)。
    当以这种方式使用时,remote.&lt;repository&gt;.fetch 值对决定获取 什么 没有任何影响(即,当命令行列出 refspecs 时,这些值不用作 refspecs);它们仅用于决定在哪里通过充当映射来存储所获取的 ref。

【讨论】:

    【解决方案4】:

    另请注意,在 Git 2.5+(2015 年第二季度)中,git merge FETCH_HEAD 可以合并多个 git fetch

    commit d45366eJunio C Hamano (gitster),2015 年 3 月 26 日。
    (由 Junio C Hamano -- gitster -- 合并,commit bcd1ecd,2015 年 5 月 19 日)

    git merge FETCH_HEAD”了解到之前的“git fetch”可能是为了创建章鱼合并,即记录多个未标记为“not-for-merge”的分支;
    这允许我们在“git pull”脚本的实现中丢失旧式调用“git merge &lt;msg&gt; HEAD $commits...”;现在可以弃用旧式语法。

    git merge doc 现在提到:

    当指定FETCH_HEAD(且没有其他提交)时,之前调用git fetch合并到.git/FETCH_HEAD文件中记录的分支合并到当前分支


    Git 2.13(2017 年第二季度)正式停用 git merge 的旧语法。
    请参阅 Junio C Hamano (gitster)commit b439165(2015 年 3 月 26 日)。
    (由 Junio C Hamano -- gitster -- 合并于 commit 1fdbfc4,2017 年 3 月 30 日)

    merge: 删除 'git merge &lt;message&gt; HEAD &lt;commit&gt;' 语法

    停止支持“git merge &lt;message&gt; HEAD &lt;commit&gt;”语法 自 2007 年 10 月起已弃用,并从 v2.5.0 开始发出弃用警告消息。

    这意味着旧式“'git merge &lt;msg&gt; HEAD &lt;commit&gt;' is deprecated.”的警告消息已不复存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 2019-04-01
      • 2015-05-24
      • 1970-01-01
      相关资源
      最近更新 更多