很难理解git-fetch

Par*_*rag 52 git git-fetch

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

我有几个问题:

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

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

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

    git-fetch <options> <repository> <refspec>
    
    Run Code Online (Sandbox Code Playgroud)

我如何使用refspec从远程主站获取内容到其远程跟踪分支?我相信如果我现在的HEAD在主人身上并且我跑了,这可能是可能的

git fetch origin master

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

还有一个问题:

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

fetch = +refs/heads/*:refs/remotes/origin/*
Run Code Online (Sandbox Code Playgroud)

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

Fel*_*peC 60

首先,没有本地跟踪分支的概念,只有远程跟踪分支.所以产地/主是一个远程跟踪分支起源回购.

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

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

最后,

fetch = +refs/heads/*:refs/remotes/origin/*
Run Code Online (Sandbox Code Playgroud)

这意味着如果你这样做

git fetch origin
Run Code Online (Sandbox Code Playgroud)

它实际上会:

git fetch origin +refs/heads/*:refs/remotes/origin/*
Run Code Online (Sandbox Code Playgroud)

这意味着远程头/ foobar将是本地遥控器/起源/ foobar,加号意味着即使它们不是快进也会更新.

也许您认为跟踪分支是与git pull和merge配置相关的东西.

  • 当你添加这个回复时,我正要开始回答这个问题.我不能说得更好.+1 (3认同)
  • @Howiecamp他们的术语令人困惑.本地分支"master"就是:本地分支.他们得到了远程跟踪分支:"origin/master".文章所讨论的是**上游**跟踪分支,但正确思考它的另一种方式是:"origin/master"是"master"的上游:它是"属性"的属性掌握"分支.这不是另一种方式:"master"不是"origin/master"的跟踪分支.https://felipec.wordpress.com/2013/09/01/advanced-git-concepts-the-upstream-tracking-branch/ (3认同)
  • 嗨 felipic,感谢您的回答。它帮助消除了我的许多疑虑。关于远程跟踪分支的一个问题。如果我理解正确,远程跟踪分支存在于我当前的存储库中,旨在跟踪其他(远程)存储库中存在的代码。如果这是真的,那么说远程跟踪分支就像远程存储库中存在的实际分支的代理是否合适? (2认同)
  • 是的,确切地说,它就像是可以随意更新的远程存储库的缓存视图。 (2认同)
  • origin/master 是 refs/remotes/origin/master 的简写。 (2认同)
  • @Howiecamp 我不会说他们错了,这是一个观点问题。`git status` 可以说你的 'master' 分支在 'origin/master' 后面,因为 'origin/master' 是 'master' 的上游跟踪分支,所以你可以说 'master' 确实跟踪 'origin/master',除了只是某些命令检查上游跟踪分支,所以可以说它是一个“跟踪分支”。对我来说,认为它**有**一个跟踪分支而不是一个跟踪分支更有用,因为您可以忽略上游跟踪分支,甚至删除它,“master”将继续工作。 (2认同)

Jak*_*ski 23

felipec已经在他的回答回答最多的问题问题.

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

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

  • 您获取的分支(<dst>in [+]<src>:<dst>)不需要驻留在remotes/<remote>/命名空间中.例如,对于镜像存储库(git clone --mirror),refspec是1到1.在过去,在单独remotes/<remote>/的远程跟踪布局之前(远程跟踪引用的名称空间之前),分支被提取到名为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/mastergit merge FETCH_HEADgit pull <URL> <branch>

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

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


Von*_*onC 5

注意,对于Git的主要维护者现在有(GIT 2.1,2014年8月)添加了这个解释git fetch
(见提交fcb14b0通过JUNIOÇ滨野(gitster

配置的远程跟踪分支

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

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

[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
Run Code Online (Sandbox Code Playgroud)

此配置有两种使用方式:

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

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