在Pro Git中,您可以看到:
从远程跟踪分支检出本地分支 自动创建所谓的
tracking branch
(和 它跟踪的分支称为 上游分支 )。跟踪分支 是与远程分支有直接关系的本地分支。 如果你在跟踪分支上并输入git pull,Git会自动进行 知道从哪个服务器获取和分支以合并到。
所以Git知道它已直接从另一个分支合并到 tracking branch
中,将这些分支命名为 downstream 似乎更好分支而不是 上游 。但为什么他们被命名为 上游 ?
答案 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 clone
为origin
设置了获取refspecs ,您可以看到:
git config --get-all remote.origin.fetch
此命令的输出将显示为:
+refs/heads/*:refs/remotes/origin/*
请注意,在冒号(:
)字符的左侧,我们看到refs/heads/*
。这些名称(常规,普通,本地)分支; *
部分匹配所有内容,因此这意味着远程上看到的每个分支。在右侧,我们看到refs/remotes/origin/*
。这些名称是远程跟踪分支 - 特别是我们自己的远程跟踪分支,用于名为origin
的远程分支。在*
。{sup> 2 期间origin
与git 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 merge
或git 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 fetch
从git pull
开始,然后运行git fetch
}或git merge
。这是一个方便的捷径,因为想要合并或重新组合,然后在最后一刻记住你还需要先git rebase
,这很常见。不过,对于初学者来说,我认为将这两个步骤分开会更好。