很难理解 git-fetch

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1070496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:40:01  来源:igfitidea点击:

Having a hard time understanding git-fetch

gitgit-fetch

提问by Parag

I am having a hard time understanding the nuances of git-fetch. I understand that doing a fetch, fetches the remote refs into a local tracking branch.

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

I have a few questions though:

不过我有几个问题:

  1. Can it be possible that a local tracking branch does not exist? If so, will it then be created automatically?

  2. What will happen if I do a fetchand specify a non tracking branch as the destination?

  3. The man page for git-fetch specifies:

    git-fetch <options> <repository> <refspec>
    
  1. 是否有可能不存在本地跟踪分支?如果是这样,它会自动创建吗?

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

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

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

How would I use the refspec to fetch contents from my remote master into its remote tracking branch? I believe this may be possible if my current HEAD is on master and I run

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

git fetch origin master

git fetch origin master

However, can I use the <+?src:dest>refspec to achieve the same thing? I think this will help me understand the concepts better.

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

And one more question:

还有一个问题:

My .git/config file has the following line for fetching (showing only relevant lines):

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

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

Can someone please explain what this line exactly means?

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

回答by FelipeC

First, there's no such concept of local trackingbranches, only remote trackingbranches. So origin/masteris a remote tracking branch for masterin the originrepo.

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

Typically you do git fetch $remotewhich updates all your remote tracking branches, and creates new ones if needed.

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

However, you can also specify a refspec, but that will not touch your remote tracking branches, instead, it will fetch the branch you specified and save it on FETCH_HEAD, unless you specify a destination. In general you don't want to mess with this.

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

Finally,

最后,

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

That means if you do

这意味着如果你这样做

git fetch origin

It will actually do:

它实际上会:

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

Which means a remote heads/foobarwill be local remotes/origin/foobar, and the plus sign means they'll be updated even if they are not fast-forward.

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

Perhaps what you think as a tracking branch is something related to git pulland the merge config.

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

回答by Jakub Nar?bski

felipechave answered most of issues in question in his answer.

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

A few remaining (most taken from git fetchmanpage; which is a bit dated in some places, unfortunately):

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

  • If remote-tracking branch(branch which tracks some branch in some remote repository) does not exists, it would be created.

  • The branch you fetch into (the <dst>in [+]<src>:<dst>) doesn't need to reside in remotes/<remote>/namespace. For example for mirroring repositories (git clone --mirror) refspec is 1 to 1. In old days before separate remotes layout (before remotes/<remote>/namespace for remote-tracking refs) masterbranch was fetched into branch called origin. Even currently tags are fetched directly into tags/namespace in mirroring fashion.

  • If branch you are fetching into (the right hand side of refspec <src>:<dst>does exist, Git would check if download would result in fast-forward, i.e. if current state in <dst>is ancestor of state in <src>in given remote repository. If it isn't, and you don't use -f/--forceoption to git-fetch, or prefix refspec with '+' (use +<src>:<dst>refspec) fetch would refuse to update that branch.

  • git fetch origin masteris equivalent to git fetch origin master:, not to git fetch origin master:master; it stores fetched value of masterbranch (of remote origin) in FETCH_HEAD, and not in masterbranch or remote-tracking remotes/origin/masterbranch. It can be followed by git merge FETCH_HEAD. Usually not used directly, but as part of one-time pull without setting remote-tracking branch: git pull <URL> <branch>.

  • +refs/heads/*:refs/remotes/origin/*as value for remote.origin.fetchconfiguration variable means that each branch (ref in refs/heads/namespace) in remote originis fetched into respectively named remote-tracking branch in refs/remotes/origin/namespace, e.g. masterbranch in origin(i.e. refs/heads/masterref) would be fetched into origin/masterremote-tracking branch (i.e. refs/remotes/origin/masterref). The '+' prefix means that fetch would succeed even in non fast-forward case, which means when branch on remote is rebased, or rewound (reset to some state in past) or otherwise amended.

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

  • 您获取的分支(<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/master分支中。后面可以跟git merge FETCH_HEAD. 通常不直接使用,而是作为一次性拉取的一部分而不设置远程跟踪分支:git pull <URL> <branch>.

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

Sidenote:You would probably want to use higher level git remotecommand to manage remote repositories and get updates.

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

回答by VonC

Note that the main maintainer for Git has now (Git 2.1, August 2014) added this explanation for git fetch:
(See commit fcb14b0by Junio C Hamano (gitster):

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

CONFIGURED REMOTE-TRACKING BRANCHES

配置的远程跟踪分支

You often interact with the same remote repository by regularly and repeatedly fetching from it. In order to keep track of the progress of such a remote repository, git fetchallows you to configure remote.<repository>.fetchconfiguration variables.

Typically such a variable may look like this:

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

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

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

This configuration is used in two ways:

  • When git fetchis run without specifying what branches and/or tags to fetch on the command line, e.g. git fetch originor git fetch, remote.<repository>.fetchvalues are used as the refspecs---they specify which refs to fetch and which local refs to update.
    The example above will fetch all branches that exist in the origin(i.e. any ref that matches the left-hand side of the value, refs/heads/*) and update the corresponding remote-tracking branches in the refs/remotes/origin/*hierarchy.

  • When git fetchis run with explicit branches and/or tags to fetch on the command line, e.g. git fetch origin master, the <refspec>s given on the command line determine what are to be fetched (e.g. masterin the example, which is a short-hand for master:, which in turn means "fetch the 'master' branch but I do not explicitly say what remote-tracking branch to update with it from the command line"), and the example command will fetch onlythe 'master' branch.
    The remote.<repository>.fetchvalues determine which remote-tracking branch, if any, is updated.
    When used in this way, the remote.<repository>.fetchvalues do not have any effect in deciding whatgets fetched (i.e. the values are not used as refspecs when the command-line lists refspecs); they are only used to decide wherethe refs that are fetched are stored by acting as a mapping.

此配置有两种使用方式:

  • 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 存储在哪里

回答by VonC

Note also that, with Git 2.5+ (Q2 2015), git merge FETCH_HEADcan merge multiple git fetch's.

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

See commit d45366eby Junio C Hamano (gitster), 26 Mar 2015.
(Merged by Junio C Hamano -- gitster--in commit bcd1ecd, 19 May 2015)

提交d45366e通过JUNIOÇ滨野(gitster,3月26日2015年
(由合并JUNIOÇ滨野- gitster-提交bcd1ecd,2015年5月19日)

"git merge FETCH_HEAD" learned that the previous "git fetch" could be to create an Octopus merge, i.e. recording multiple branches that are not marked as "not-for-merge";
this allows us to lose an old style invocation "git merge <msg> HEAD $commits..." in the implementation of "git pull" script; the old style syntax can now be deprecated.

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

The git mergedocnow mention:

git mergeDOC提现:

When FETCH_HEAD(and no other commit) is specified, the branches recorded in the .git/FETCH_HEADfile by the previous invocation of git fetchfor merging are merged to the current branch.

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



Git 2.13 (Q2 2017) officially retires the old syntax for git merge.
See commit b439165(26 Mar 2015) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster--in commit 1fdbfc4, 30 Mar 2017)

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

merge: drop 'git merge <message> HEAD <commit>' syntax

Stop supporting "git merge <message> HEAD <commit>" syntax that has been deprecated since October 2007, and issues a deprecation warning message since v2.5.0.

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

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

That means the warning message old-style "'git merge <msg> HEAD <commit>' is deprecated." is no more.

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