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

时间:2019-01-13 01:15:58

标签: git

git checkout的联机帮助页上说:

git checkout <branch>
     

如果未找到<branch>,但确实存在一个跟踪分支   恰好是一个具有匹配名称的遥控器(称为<remote>),将其视为   等同于

$ git checkout -b <branch> --track <remote>/<branch>
{p>,git checkout的联机帮助页上说,

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

默认情况下,-t的{​​{1}}选项为git branch(来自git branch的联机帮助页)

-t
     

创建新分支时,请设置branch.<branch>.remotebranch.<branch>.merge   配置条目,以将起点分支标记为新分支的“上游”。

等效的<remote>/<branch>命令和git checkout命令中的git branch代表什么?

  1. 由于git branch命令将branch.<branch>.remotebranch.<branch>.merge设置为远程存储库和远程分支,因此<remote>/<branch>代表远程分支(上游分支)?

  2. 由于git branch命令从<remote>/<branch>开始创建新的本地分支,因此<remote>/<branch>代表远程跟踪分支吗?

谢谢。

2 个答案:

答案 0 :(得分:5)

git help revisions将告诉您如何解释refname。

作为参考

  

<refname>,例如masterheads/masterrefs/heads/master
         符号引用名称。例如。 master通常是指refs / heads / master引用的提交对象。如果          您碰巧同时拥有heads / master和tags / master,您可以明确说出heads / master告诉Git          你的意思是哪一个。如果模棱两可,则通过参加第一场比赛来消除a的歧义          以下规则:

     
      
  1. 如果$ GIT_DIR / 存在,这就是您的意思(通常仅对HEAD,FETCH_HEAD,ORIG_HEAD,MERGE_HEAD和CHERRY_PICK_HEAD有用);
  2.   
  3. 否则,使用refs / (如果存在)
  4.   
  5. 否则,使用refs / tags / (如果存在)
  6.   
  7. 否则,使用refs / heads / (如果存在)
  8.   
  9. 否则,引用/删除/ (如果存在)
  10.   
  11. 否则,引用/远程/ / HEAD(如果存在)。

         

    HEAD在工作树中命名所做更改的提交。 FETCH_HEAD记录   您使用上一次git fetch调用从远程存储库获取的分支。 “ ORIG_HEAD”为   由命令以剧烈方式移动HEAD所创建,以记录HEAD之前的位置   它们的操作,以便您可以轻松地将分支的尖端更改回运行之前的状态   他们。 MERGE_HEAD记录运行git时要合并到分支中的提交   合并。 CHERRY_PICK_HEAD记录您在运行git时正在挑选的提交   摘樱桃。

         

    请注意,上述任何refs / *情况都可能来自$ GIT_DIR / refs目录或   $ GIT_DIR / packed-refs文件。虽然未指定参考名称编码,但最好使用UTF-8   输出处理可以假定引用名称为UTF-8。

         

    @
             @单独是HEAD的快捷方式。

  12.   

因此,当您说origin/master并且Git在那里的仓库中寻找东西时,它将根据该列表进行搜索,除非您习惯使用分支或标签前缀来修剪远程名称,否则它将找到远程跟踪引用refs/remotes/origin/master

(请注意,有很多便捷的方法可以在Git中引用此版本或该版本的修订,请参见文档)。

答案 1 :(得分:4)

请参见jthill's answer,以了解事物的正常运行方式,即事物应该如何运行。

但是,如果您将remote.origin.fetch配置为一组不寻常的字符串,那么这里会有一个令人讨厌的小皱纹。 git fetchgit checkout(实际上,任何使用分支上游的东西)都使用Git称为 refmap 的数据结构结束。 请注意,据我所知,从来没有任何正当理由我要描述的事情。但是, Git 确实做到了(基于用户的配置),因此在编写自己的代码以使用 Git配置

时,如果我们希望正确地对Git进行编程,则必须了解其行为。

例如,假设您以这种方式配置remote.origin.fetch

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

现在运行时:

git fetch origin

您通常会得到他们的refs/heads/master并将其记录在自己的存储库中,称为refs/remotes/origin/master。但是您将分别对待他们的refs/heads/develop ,在您自己的存储库中创建或更新自己的refs/remotes/origin/weird_develop

因此,您记住 masterdevelop的远程跟踪分支在<中被称为origin/masterorigin/weird_develop(简称) em>您的存储库,即使它们在存储库中被称为masterdevelop

现在假设您要创建自己的名为develop的分支。如果您使用的是合理 fetch =配置,则其上游设置(git rev-parse --abbrev-ref develop@{upstream}打印的内容)将为origin/develop。但是出于某些(不是理智的?)原因,您已经配置了fetch =这套相当奇怪的设置,因此运行git fetch会创建或更新一个奇怪的远程跟踪名称。

尽管远程跟踪名称很奇怪,但分支配置将使用上游的实际分支名称。即,在执行以下操作后检查.git/config

git checkout --track develop origin/weird_develop

您将看到:

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

您应该问的问题是:当我的上游设置为refs/heads/develop时,Git是如何将origin/weird_develop放入此条目的?

答案是Git构建了 refmap 这个东西,说他们的(来源)refs/heads/develop是您的refs/remotes/origin/weird_develop。此refmap有两种方式:Git可以查找其refs/heads/develop来查找您的远程跟踪名称,或者Git可以查找您的refs/remotes/origin/weird_develop以查找来源的分支名称。

要使所有这些工作正常进行,从fetch =设置构造的refmap不得动态更改。也就是说,如果您编辑.git/config文件并半随机更改fetch行,一旦构造的refmap不再与现实匹配,或者您创建了不是正确的双射。 1


在这里,通过 bijection ,我的意思是您从远程复制的每个名称都应映射到您自己的存储库中的唯一远程跟踪名称,并且该名称应涵盖整个远程-跟踪存储库中的名称。 +refs/heads/*:refs/remotes/origin/*的简单情况显然符合此条件。但是,例如,如果您说:

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

您已经在源到本地存储库的方向上创建了多值函数,因为master必须复制为两个名称,并且因为您的origin/masterorigin/extra_master都映射到了他们的master,所以反向映射。在这种情况下,Git会因各种错误而停止。