上游分支是否是远程分支?

时间:2017-07-09 10:32:43

标签: git

我成功运行了2个命令。所以它让我认为上游分支不一定是远程分支。那么本地上游分支有什么用呢?

$ git branch local_branch5 --set-upstream origin/branch5
Branch local_branch5 set up to track remote branch branch5 from origin.

$ git branch local_branch6 --set-upstream local_branch3
Branch local_branch6 set up to track local branch local_branch3.

我的分支看起来像这样:

$ git branch -vv
  local_branch3          a758e52 Initial commit
* local_branch4          db11990 Update README.md
  local_branch5          ce0762c [origin/branch5] change on local_branch2
  local_branch6          a758e52 [local_branch3] Initial commit
  master                 064aa08 [origin/master: ahead 1] change on local master

ADD 1

正如我测试的那样,似乎所谓的upstream只是在2个分支/命名提交之间创建关系。这些分支可以是本地分支,也可以是本地远程分支。只需要注意,当推送到本地上游时,repo需要是.

1 个答案:

答案 0 :(得分:2)

您是对的,本地分支机构可以将其他本地分支作为其上游设置。我改写了你的" ADD 1 "部分说它是设置的远程部分,必须是.,上游才是另一个普通的,即本地分支。

有关相关问题和各种答案,请参阅how do I get git to show me which branches are tracking what?

您可以忽略以下所有内容。它不是答案的真正部分,它只是解释了我们如何到达这里,以及为什么有些怪癖他们是这样的。

更深的历史/ Git魔法

还值得注意的是,本地分支具有上游,并且该上游设置以非常低的级别配置为两部分。但是,这两个中的一个使用第三部分,即使在正常设置中,这第三部分几乎是不可见的。其原因具有历史意义,可追溯到2007年之前使用的Git版本。

如果您查看每个存储库配置 - 文件.git/configgit config --list --local的输出 - 您将看到如下文字:

$ git config --list --local
[snip]
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
[snip]
branch.master.remote=origin
branch.master.merge=refs/heads/master

这意味着(本地)分支master具有origin/master作为其上游。这两部分是branch.master.remote,告诉Git使用远程,以及branch.master.merge,它似乎再次引用您自己的本地主服务器。那是什么?

在远程跟踪分支存在之前

答案在于,Git的远程跟踪分支本身并非早期史前存在,因为它是Git。回到过去的糟糕时光,你的 Git不记得你其他一些Git存储库的状态。

当你连接到其他(上游)Git并从中提取提交时,你实际上会从他们的 master分支获取提交。事实上,这仍然是今天发生的事情。您的Git会将此信息放入文件.git/FETCH_HEAD中,并说:&#34;当我查看<url>时,我找到了一个名为master的分支,其中包含b06d364...& #34 ;.你的Git今天仍然这样做。但是你的Git只会停止: FETCH_HEAD这些东西就是你所拥有的。

所以,此时你有两个 master - s:你的,以及他们的。两者都名为master。在您的FETCH_HEAD内容被任何其他不同的上游结果覆盖之前,您的Git必须立即重新提交或合并您的提交。这意味着你的Git需要知道,当你想要重新绑定或与你的上游合并时,它应该获得他们的master,然后使用master中的信息重新绑定或合并你的.git/FETCH_HEAD名称为master

因此,branch.master.*设置分为两部分:remote = origin - 这曾经只是一个原始网址 - 然后是merge = master。当时的假设是,现在仍然是,行动应该是合并,即使rebase可以说是更好的默认。 pull脚本将从URL获取,然后使用.git/FETCH_HEAD的内容获取合并的提交哈希:

$ head -3 .git/FETCH_HEAD | sed 's,git://.*,<url>,'
b06d3643105c8758ed019125a4399cb7efdcce2c                branch 'master' of <url>
95d67879735cfecfdd85f89e59d993c5b4de8835        not-for-merge   branch 'maint' of <url>
4ebf3021692df4cb51da8d806fbb8b909ee7e111        not-for-merge   branch 'next' of <url>

请注意其中一些 - 实际上除了一个之外 - 其中包含字符串not-for-merge。这是对原始git pull脚本的提示:只有master行才能用于合并。

输入遥控器

早期的Git用户很快就会明白,使用比完整网址更短的名称是很好的,特别是如果你有几个不同的其他Git存储库,你经常会从中获得好的工作。您可以只说protocol://some.university.ac.uk/long/path/to/brians/repo

,而不是输入brian

这种情况的确切机制显然是一种竞赛,或者是以不同的方式多次独立发明的。我自己并没有参与这段历史,但是traces linger even today in the git fetch documentation, under the section named remotes

  

可以使用以下某个名称而不是URL作为<repository>参数:

     
      
  • Git配置文件中的遥控器:$GIT_DIR/config

  •   
  • $GIT_DIR/remotes目录中的文件或

  •   
  • $GIT_DIR/branches目录中的文件。

  •   

远程跟踪分支

第一个选项&#34;赢了&#34;是人们今天真正使用的东西。 (其他两个仍然受到支持。我不知道为什么 - 他们似乎已经被弃用,然后在不久前被弃用。)

因为第一个选项赢了,我们可以转到the configured remote-tracking branches section of this same documentation

  

您经常通过定期重复从中获取相同的远程存储库。为了跟踪这种远程存储库的进度,git fetch允许您配置remote.<repository>.fetch配置变量。

     

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

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

这(以及本节的其余部分)定义远程跟踪分支名称的工作方式。这个想法的核心是,嘿,那里还有另一个Git:我们运行git fetch brian来获得Brian的东西。我们不能记得:这是Brian的Git说他有的东西,我们最后一次打电话给他的Git

当然,我们可以:我们会通过将Brian的master更改为brian/master来实现这一目标。我们存储在我们自己的Git中的映射,从Brian的分支名称到我们的远程跟踪名称,来自此fetch = ...行,我们控制。每个fetch行 - 可以有多个 - 具有+src:dst形式,其中前导加号 - 与--force相同,或多或少 - 是可选的但几乎总是现在,结肠的左侧和右侧给出了他们的名字&#34;和#34;我们的名字&#34;对于我们打算复制的每个参考文献。

对于远程 R src 部分只是refs/heads/*的情况几乎总是如此dst 部分以refs/remotes/开头,然后列出远程名称​​ R 本身。因此,当我们有一个名为brian的遥控器时,fetch设置为+refs/heads/*:refs/remotes/brian/*

两个星号相匹配:Brian有(refs/heads/*)强制复制(+)到我们自己的存储库的任何分支,但重命名为我们的< em>远程跟踪分支名称空间(refs/remotes/)。我们添加了另一个字词,以确保 Brian 分支机构位于我们的refs/remotes/brian/下,并且在我们的refs/remotes/nadia/下与 Nadia的分支发生冲突。然后我们只是复制Brian(或者Nadia&#39; s,或者来源&#39) ; s)分支名称,它成为此分支的远程跟踪分支名称

如何与本地分支机构分支@ {upstream}

联系起来

大多数本地分支都有远程跟踪分支作为其上游设置。 (正如这个问题所指出的那样,实际上不需要,这只是通常情况。)但是,当本地分支 B &#34; track&#34; -ie,作为其上游远程跟踪分支refs/remotes/origin/B,配置条目只是说branch.B.remoteoriginbranch.B.merge B 。那里根本没有明确的refs/remotes/origin/B

这都是因为上面曲折的历史(扭曲?)。在根本没有任何远程跟踪分支之前,Git的配置列出了在远程上找到的分支的名称。分支 B &#34;与&#34;合并分支 origin B版本。由于 在2005年左右拼写,因此Git要求今天拼写。然后Git接受旧的拼写并将其映射到fetch =行以找出正确的远程跟踪分支。

例如,假设您有上游test的分支origin/master。也就是说,git config --list --local将包括:

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

(通常和正常的模式)和:

branch.test.remote=origin
branch.test.merge=refs/heads/master

考虑到所有Git都将远程名称originmaster的{​​{1}}部分串在一起,得到branch.test.merge=refs/heads/master,可以原谅。但实际上,事情并非如此。让我们制作另一个遥控器,然后更改origin/master行:

fetch

现在我们将运行git remote add weird <url> git config remote.weird.fetch '+refs/heads/*:refs/remotes/twisty/*'

git fetch weird

请注意,他们没有转到$ git fetch weird From <url> * [new branch] maint -> twisty/maint * [new branch] master -> twisty/master * [new branch] next -> twisty/next * [new branch] pu -> twisty/pu * [new branch] todo -> twisty/todo ,而是转到weird/*。我们现在可以创建一个跟踪(作为其上游)twisty/*

的分支
twisty/master

遥控器为$ git checkout -b test --track twisty/master Branch test set up to track remote branch master from weird. Switched to a new branch 'test' $ git rev-parse --symbolic-full-name test@{upstream} refs/remotes/twisty/master $ git config --list --local [snip] branch.test.remote=weird branch.test.merge=refs/heads/master ,而weird从未提及merge,但上游确实 twisty

清理

由于我真的不想要测试分支和奇怪的扭曲设置,让我们清理它们:

twisty/master

我们需要在此完成所有操作:$ git checkout master ... $ git branch -D test Deleted branch test (was 8b2efe2a0). $ git remote remove weird 删除所有git remote remove weird远程跟踪分支,因为它也遵循twisty/*配置行。