令人困惑的Git分支名称:上游或下游?

时间:2016-03-28 17:18:08

标签: git version-control merge

Pro Git中,您可以看到:

  

从远程跟踪分支检出本地分支   自动创建所谓的tracking branch(和   它跟踪的分支称为 上游分支 )。跟踪分支   是与远程分支有直接关系的本地分支。   如果你在跟踪分支上并输入git pull,Git会自动进行   知道从哪个服务器获取和分支以合并到。

所以Git知道它已直接从另一个分支合并到 tracking branch中,将这些分支命名为 downstream 似乎更好分支而不是 上游 。但为什么他们被命名为 上游

1 个答案:

答案 0 :(得分:1)

对我来说并不完全清楚,但我认为这是你混淆的根源:

  

所以Git知道它已直接从另一个分支合并到 tracking branch ......

这是错误的。这不是远程跟踪分支的功能。

首先,让我们记下git引用是如何工作的。无论实际引用(分支名称,标记名称,refs/stash命令的git stash或其他),git中的引用只是一个解析为的名称哈希,例如0f90a088a1161e812e7cf9ef9724f9bfcb4267ec。大多数(尽管不是全部)引用都有一个以refs/开头的全名。 (有些引用是间接符号,这意味着它们包含另一个引用的名称。特殊的HEAD引用 - 这是少数无法启动的引用之一with refs/ - 通常是符号,因为它通常包含当前分支的名称。符号引用最终必须解析为常规引用,而必须依次解析为其中一个SHA- 1个哈希值,git称之为未出生的分支的一个特殊例外,我在这里不会解决这个问题。)

接下来,让我们定义术语"远程跟踪分支&#34 ;:一个远程跟踪分支,在git中,只是任何以其全名开头的引用refs/remotes/。类似地,(常规,普通,非远程跟踪)分支 1 是全名以refs/heads/开头的任何引用(为完整性,标记是全名以refs/tags/开头的任何引用。

通常,您的(单个)遥控器名为origin,因为git clone url会创建一个名为origin的遥控器。这意味着您的本地git存储库具有origin/master作为其远程跟踪分支之一。 origin/master的全名实际上是refs/remotes/origin/master,根据定义,它使其成为远程跟踪分支。

最初的git clone url做了另外一件你通常不需要调整的事情,但知道它是有用的,因为它实际上是远程跟踪分支的实现方式。 git cloneorigin设置了获取refspecs ,您可以看到:

git config --get-all remote.origin.fetch

此命令的输出将显示为:

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

请注意,在冒号(:)字符的左侧,我们看到refs/heads/*。这些名称(常规,普通,本地)分支; *部分匹配所有内容,因此这意味着远程上看到的每个分支。在右侧,我们看到refs/remotes/origin/*。这些名称是远程跟踪分支 - 特别是我们自己的远程跟踪分支,用于名为origin的远程分支。在*。{sup> 2 期间origingit fetch连接时,+替换为我们的git匹配的任何内容(为了完整性,前面的git fetch设置 force 标志,以便git fetch始终更新远程跟踪分支。)

这意味着每当您从遥控器中取出时,您的git都会使您的远程跟踪分支与其git的分支相匹配。它确实通过进行任何合并,只需通过复制他们拥有的任何内容,然后创建或替换远程跟踪分支,使其在{{>时完全匹配他们拥有的 1}}跑。

这意味着远程跟踪分支是你的git告诉你"这是我在最后一次检查时在遥控器上看到的。"

这也是为什么我们可以将遥控器称为"上游"。例如,假设远程origin引用某个项目的官方github存储库。您将项目克隆到本地存储库(甚至不是另一个github fork,只是本地计算机上的常规git存储库),并且可能会进行一些更改。然后,过了一段时间,您可能会决定找出自克隆以来在官方存储库中发生了什么。您只需运行git fetch origin即可获取更改。如果他们更改了master分支,您将立即自动在origin/master远程跟踪分支中看到这些更改。

由于你的工作来自他们的工作,你的代码是"下游"他们的,他们的是#34;上游"你的。一旦你完成了他们的新工作,它取决于你如何,甚至是否修改你之前的更改以使用他们的新版本。你可以将他们的新作品,rebase合并到他们的新作品上,忽略他们的工作,或做任何你喜欢的事情 - 但只要你的工作是基于他们的,他们就是上游"你和你是#34;下游"他们。

如果您的本地分支 - 无论其名称是master还是其他名称 - 都将您的远程跟踪分支设置为"上游" (使用git branch --set-upstream-to或类似内容),git status命令会在您git fetch之后告诉您有关他们不会提交的提交("提前3&#34) ;)并承诺他们没有("在9"后面)。然后,您可以使用git mergegit rebase将您的更改与他们的内容合并或更改,但这是自动的,只有在您告知时才会完成你的git去做 3

1 git中的术语 branch 实际上是不明确的:它可能意味着分支名称,这是以{{ 1}},或者它可以引用提交图的一部分。有关详细信息,请参阅this question

2 一段时间以来,由于git 1.8左右,git还机会性地更新refs/heads/操作上的远程跟踪分支。具体来说,如果您在 git push 上运行git push remote ref并且推送成功更新 ref ,那么推送代码也会更新您的远程跟踪分支 remote ' remote 。例如,在成功ref之后,您的git知道git push origin master应指向的位置,因此您的git会更新origin/master的副本。

3 如果您运行origin/master而不是git pull,请知道git fetchgit pull开始,然后运行git fetch }或git merge。这是一个方便的捷径,因为想要合并或重新组合,然后在最后一刻记住你还需要先git rebase,这很常见。不过,对于初学者来说,我认为将这两个步骤分开会更好。