57

我很难理解 git-fetch 的细微差别。我知道做fetch, 将远程 refs 提取到本地跟踪分支中。

不过我有几个问题:

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

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

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

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

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

git fetch origin master

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

还有一个问题:

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

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

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

4

4 回答 4

64

首先,没有本地跟踪分支的概念,只有远程跟踪分支。所以origin/master是原始仓库中master的远程跟踪分支。

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

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

最后,

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

这意味着如果你这样做

git fetch origin

它实际上会这样做:

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

这意味着远程head/foobar将是本地remotes/origin/foobar,加号意味着即使它们不是快进的,它们也会被更新。

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

于 2009-07-01T19:18:02.070 回答
24

felipec在他的回答中回答了大部分问题

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

  • 如果远程跟踪分支(跟踪某个远程存储库中的某个分支的分支)不存在,它将被创建。

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

  • 如果您正在获取分支(refspec 的右侧<src>:<dst>确实存在,Git 将检查下载是否会导致快进,即当前状态是否是给定远程存储库<dst>中状态的祖先<src>。如果不是,并且您不使用-f/--force选项来 git-fetch,或者在 refspec 前加上 '+'(使用+<src>:<dst>refspec) fetch 将拒绝更新该分支。

  • git fetch origin master等于git fetch origin master:,不等于git fetch origin master:master;它将获取的分支(远程来源)的值存储在FETCH_HEAD中,而不是在分支或远程跟踪remotes/origin/master分支中。后面可以跟git merge FETCH_HEAD。通常不直接使用,而是作为一次性拉取的一部分,无需设置远程跟踪分支:git pull <URL> <branch>.

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

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

于 2009-07-01T20:44:05.470 回答
5

请注意,Git 的主要维护者现在(Git 2.1,2014 年 8 月)添加了以下解释git fetch:(
参见Junio C Hamano的提交 fcb14b0 ( gitster

已配置的远程跟踪分支

您经常通过定期和重复地从同一个远程存储库中获取来与它进行交互。为了跟踪此类远程存储库的进度,git fetch允许您配置remote.<repository>.fetch配置变量。

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

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

此配置以两种方式使用:

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

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

于 2014-08-02T18:00:56.790 回答
2

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

请参阅Junio C Hamano ( )提交 d45366e ,2015 年 3 月 26 日。(由Junio C Hamano 合并 -- --提交 bcd1ecd中,2015 年 5 月 19 日)gitster
gitster

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

git merge文档现在提到:

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


Git 2.13(2017 年第二季度)正式淘汰了git merge.
请参阅Junio C Hamano ( ) 的提交 b439165(2015 年 3 月 26 日(由Junio C Hamano 合并 -- --提交 1fdbfc4中,2017 年 3 月 30 日)gitster
gitster

merge: 删除 ' git merge <message> HEAD <commit>' 语法

停止支持git merge <message> HEAD <commit>自 2007 年 10 月起已弃用的 " " 语法,并从 v2.5.0 开始发出弃用警告消息。

这意味着旧式“ 'git merge <msg> HEAD <commit>' is deprecated.”的警告消息不再存在。

于 2015-05-24T16:56:17.113 回答