简体   繁体   English

是否` <remote> / <branch> 这个`git checkout`命令中的`代表远程分支还是远程跟踪分支?

[英]Does `<remote>/<branch>` in this `git checkout` command represent a remote branch or a remote tracking branch?

The manpage of git checkout says: git checkout的手册页说:

 git checkout <branch> 

If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote> ) with a matching name, treat as equivalent to 如果未找到<branch>但确实在一个具有匹配名称的远程站点(称为<remote> )中存在跟踪分支,则将其等同于

 $ git checkout -b <branch> --track <remote>/<branch> 

which, the manpage of git checkout says, invokes git checkout的联机帮助页面说

$ git branch -f <branch> <remote>/<branch>

with -t option to git branch by default (from manpage of git branch ) 带有-t选项的git branch默认情况下(来自git branch帮助页)

 -t 

When creating a new branch, set up branch.<branch>.remote and branch.<branch>.merge configuration entries to mark the start-point branch as "upstream" from the new branch. 创建新分支时,请设置branch.<branch>.remotebranch.<branch>.merge配置条目,以将起点分支标记为新分支的“上游”。

What does <remote>/<branch> in the equivalent git checkout command and in the git branch command represent? 等效的git checkout命令和git branch命令中的<remote>/<branch>代表什么?

  1. Since the git branch command sets up branch.<branch>.remote and branch.<branch>.merge to be a remote repository and a remote branch, does <remote>/<branch> represent the remote branch (the upstream branch to-be)? 由于git branch命令设置了branch.<branch>.remotebranch.<branch>.merge成为远程存储库和远程分支,因此<remote>/<branch>代表了远程分支(上游分支为-是)?

  2. Since the git branch command create a new local branch starting from <remote>/<branch> , does <remote>/<branch> represent the remote tracking branch? 由于git branch命令从<remote>/<branch>创建一个新的本地分支,所以<remote>/<branch>代表远程跟踪分支吗?

git help revisions will tell you how a refname is interpreted. git help revisions将告诉您如何解释refname。

For reference, 以供参考,

<refname> , eg master , heads/master , refs/heads/master <refname> ,例如masterheads/masterrefs/heads/master
A symbolic ref name. 符号引用名称。 Eg master typically means the commit object referenced by refs/heads/master. 例如,master是指由refs / heads / master引用的提交对象。 If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean. 如果您碰巧同时拥有heads / master和tag / master,则可以明确地说出heads / master来告诉Git您是什么意思。 When ambiguous, a is disambiguated by taking the first match in the following rules: 当模棱两可时,通过遵循以下规则中的第一个匹配项来消除a的歧义:

  1. If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD); 如果$ GIT_DIR / <refname>存在,这就是您的意思(通常仅对HEAD,FETCH_HEAD,ORIG_HEAD,MERGE_HEAD和CHERRY_PICK_HEAD有用);
  2. otherwise, refs/<refname> if it exists; 否则,refs / <refname>(如果存在);
  3. otherwise, refs/tags/<refname> if it exists; 否则,使用refs / tags / <refname>(如果存在);
  4. otherwise, refs/heads/<refname> if it exists; 否则,refs / heads / <refname>(如果存在);
  5. otherwise, refs/remotes/<refname> if it exists; 否则,引用/远程/ <refname>(如果存在);
  6. otherwise, refs/remotes/<refname>/HEAD if it exists. 否则,引用/远程/ <refname> / HEAD(如果存在)。

    HEAD names the commit on which you based the changes in the working tree. HEAD命名工作树中所做更改的基础提交。 FETCH_HEAD records the branch which you fetched from a remote repository with your last git fetch invocation. FETCH_HEAD记录您最近一次git fetch调用从远程存储库获取的分支。 ORIG_HEAD is created by commands that move your HEAD in a drastic way, to record the position of the HEAD before their operation, so that you can easily change the tip of the branch back to the state before you ran them. ORIG_HEAD是由命令创建的,这些命令以剧烈的方式移动HEAD,以在操作之前记录HEAD的位置,以便您可以轻松地将分支的尖端更改回运行之前的状态。 MERGE_HEAD records the commit(s) which you are merging into your branch when you run git merge. MERGE_HEAD记录运行git merge时要合并到分支中的提交。 CHERRY_PICK_HEAD records the commit which you are cherry-picking when you run git cherry-pick. CHERRY_PICK_HEAD记录您在运行git cherry-pick时正在选择的提交。

    Note that any of the refs/* cases above may come either from the $GIT_DIR/refs directory or from the $GIT_DIR/packed-refs file. 请注意,上面的任何refs / *案例都可能来自$ GIT_DIR / refs目录或$ GIT_DIR / packed-refs文件。 While the ref name encoding is unspecified, UTF-8 is preferred as some output processing may assume ref names in UTF-8. 虽然未指定引用名称编码,但首选使用UTF-8,因为某些输出处理可能会假定UTF-8中使用了引用名称。

    @
    @ alone is a shortcut for HEAD. @单独是HEAD的快捷方式。

So when you say origin/master and Git's looking for something in the repo there, it'll search according to that list and unless you've taken to punning your remote names with branch or tag prefixes it'll find the remote-tracking ref refs/remotes/origin/master . 因此,当您说origin/master且Git在那里的仓库中寻找东西时,它将根据该列表进行搜索,除非您习惯使用分支或标签前缀来修剪远程名称,否则它将找到远程跟踪引用refs/remotes/origin/master

(note that there are a lot of handy ways to refer to this or that set of revisions in Git, see the docs). (请注意,有很多便捷的方法可以在Git中引用此版本或该版本的修订,请参见文档)。

See jthill's answer for how things work normally, which is how they should work. jthill的答案的事情通常是如何工作的,这是他们应该如何工作。

There's a nasty little wrinkle here if you configure your remote.origin.fetch to an unusual set of strings, though. 但是,如果将remote.origin.fetch配置为一组不寻常的字符串,那么这里会有一个令人讨厌的小皱纹。 Both git fetch and git checkout —well, anything that uses a branch's upstream, really—wind up using a data structure that Git calls a refmap . git fetchgit checkout (实际上,任何使用分支上游的东西)都使用Git调用refmap的数据结构结束 Note that there is never, as far as I can tell, any good reason to do what I am about to describe. 请注意,据我所知,从来没有任何正当理由我将要描述的事情。 But Git does it (based on the user's configuration), so we must be aware of its behavior if we wish to program Git correctly when writing our own code to use Git configurations. 但是Git会这样做 (基于用户的配置),因此,如果我们希望在编写自己的代码以使用 Git配置时希望正确地对Git进行编程,则必须意识到它的行为。

Let's say, for example, that you configure remote.origin.fetch this way: 例如,假设您remote.origin.fetch这种方式配置remote.origin.fetch

[remote "origin"]
    fetch = +refs/heads/master:refs/remotes/origin/master
    fetch = +refs/heads/develop:refs/remotes/origin/weird_develop

Now when you run: 现在,当您运行时:

git fetch origin

you'll get their refs/heads/master and record it in your own repository as refs/remotes/origin/master , quite normally. 您通常会得到他们的refs/heads/master并将其记录在自己的存储库中,作为refs/remotes/origin/master But you'll treat their refs/heads/develop differently , creating or updating your own refs/remotes/origin/weird_develop in your own repository. 但是,你对待他们的refs/heads/develop 不同 ,在创建或更新自己的refs/remotes/origin/weird_develop在自己的仓库。

Hence, your remote-tracking branches that remember their master and develop are called origin/master and origin/weird_develop (for short) in your repository, even though they are called master and develop in their repository. 因此,能记住他们的远程跟踪分支masterdevelop被称为origin/masterorigin/weird_develop你的仓库(简称),即使他们被称为master ,并develop 他们的仓库。

Now suppose you'd like to create your own branch named develop . 现在,假设您想创建自己的名为develop的分支。 If you were using sane fetch = configurations, its upstream setting—what git rev-parse --abbrev-ref develop@{upstream} prints—would be origin/develop . 如果您使用的是合理的 fetch =配置,则其上游设置( git rev-parse --abbrev-ref develop@{upstream}打印)将是origin/develop But for some (not-sane?) reason, you've configured this rather bizarre set of fetch = settings, so running git fetch creates or updates one weirded remote-tracking name. 但是出于某些(不是理智的?)原因,您已经配置了一组相当奇怪的fetch =设置,因此运行git fetch会创建或更新一个奇怪的远程跟踪名称。

Despite the weird remote-tracking names, the branch configurations will use the actual branch names on the upstream. 尽管远程跟踪名称很奇怪,但分支配置将在上游使用实际的分支名称。 That is, inspecting .git/config after doing: 也就是说,在执行以下操作后检查.git/config

git checkout --track develop origin/weird_develop

you will see: 你会看见:

[branch "develop"]
    remote = origin
    merge = refs/heads/develop

The question you should ask is: How did Git put refs/heads/develop into this entry, when my upstream setting is origin/weird_develop ? 您应该问的问题是: 当我的上游设置是origin/weird_develop时,Git如何将refs/heads/develop放入origin/weird_develop

The answer is that Git has built this refmap thing, that says that their (origin's) refs/heads/develop is your refs/remotes/origin/weird_develop . 答案是Git已经构建了这个refmap东西,也就是说他们的 (来源) refs/heads/develop是您的refs/remotes/origin/weird_develop This refmap goes both ways: Git can either look up their refs/heads/develop to find your remote-tracking name, or Git can look up your refs/remotes/origin/weird_develop to find origin's branch name. 此refmap有两种方式:Git可以查找其refs/heads/develop来查找您的远程跟踪名称,或者Git可以查找您的refs/remotes/origin/weird_develop来查找来源的分支名称。

For all this to work, the refmap constructed from the fetch = setting must not change dynamically. 为了使所有这些都能起作用,从fetch =设置构造的refmap不得动态更改。 That is, if you edit your .git/config file and alter the fetch lines semi-randomly, your own Git will start to behave oddly, once the constructed refmap no longer matches reality, or if you create maps that are not proper bijections. 也就是说,如果您编辑.git/config文件并半随机地更改fetch线,一旦构造的refmap不再与现实匹配,或者您创建了不正确的双射图,则您自己的Git将开始表现异常。 1 1个


By bijection here, I mean that every name that you do copy from the remote should map to a unique remote-tracking name in your own repository, and this should cover the entire set of remote-tracking names in your repository. 这里的双射是指您从远程复制的每个名称都应映射到您自己的存储库中的唯一远程跟踪名称,并且该名称应覆盖存储库中的整个远程跟踪名称集。 The simple case of +refs/heads/*:refs/remotes/origin/* obviously meets this criterion. +refs/heads/*:refs/remotes/origin/*的简单情况显然符合该标准。 However, if you say, for instance: 但是,例如,如果您说:

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

you've created a multivalued function in the origin-to-local-repository direction, since master must be copied to two names, and a surjective mapping in the reverse direction, since your origin/master and origin/extra_master both map to their master . 您已经在origin-to-local-repository方向上创建了一个多值函数 ,因为必须将master复制到两个名称,并在相反的方向上创建了一个射影映射,因为您的origin/masterorigin/extra_master都映射到了他们的master Git will stop with various errors for these cases. 对于这些情况,Git会因各种错误而停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM