“下游”和“上游”的定义

我已经开始玩Git,并遇到了“上游”和“下游”的条款。 我以前见过这些,但是完全不了解。 这些术语在SCM和源代码中意味着什么?

就源代码控制而言,从存储库复制(克隆,签出等)时,您就是“ 下游 ”。 信息stream向你的“下游”。

当你做出改变的时候,你通常希望把它们发送回“ 上游 ”,这样它们就进入了这个存储库,这样,从同一个来源拉出来的每个人都在进行所有相同的改变。 这主要是人人都能协调工作的社会问题,而不是源头控制的技术要求。 你想要把你的改变放到主项目中,所以你没有跟踪不同的发展路线。

有时你会阅读关于提交“上游”更改的软件包或发布pipe理器(人员,而不是工具)。 这通常意味着他们必须调整原始来源,以便为他们的系统创build一个包。 他们不想继续做这些改变,所以如果他们把它们“上游”地发送给原始来源,他们不应该在下一个版本中处理同样的问题。

当你在git tag手册页阅读:

git的一个重要方面是分布式的,分布式的意味着系统中没有固有的“上游”或“下游”。

,那简直意味着没有绝对的上游回购或下游回购。
这些概念在两个回购之间总是相对的,并且取决于数据stream的方式:

如果“yourRepo”声明“otherRepo”是远程的,那么

  • 从上游 “otherRepo”(“otherRepo”是“在你的上游”,而你是“下游的otherRepo”)。
  • 推动上游 (“otherRepo”仍然是“上游”,信息现在回到)。

注意“from”和“for”:你不只是“下游”,你是“下游/为了 ”,因此是相对的方面。


DVCS(分布式版本控制系统)的扭曲是:你不知道下游实际上是什么,除了你自己的回购相对于你声明的远程回购。

  • 你知道上游是什么(你正在从或推动的回购)
  • 你不知道下游是由什么组成的(另一个回购是从你的回购或者推回到你的回购 )。

基本上:

就“ 数据stream动 ”而言,您的回购处于来自上游回购(“拉出”)和返回(相同或其他)上游回购(“推入”)的stream量的底部(“下游” )。


您可以在git-rebase手册页中看到一个插图,其中的段落“RECOVERING FROM UPSTREAM REBASE”:

这意味着你正在从一个“上游”回购的地方进行重新设置 ,而你(“下游”回购)的结果是坚持的(大量重复的提交,因为分支重新启动上游重新创build了同一分支的提交)有本地)。

这是不好的,因为对于一个“上游”回购,可能会有许多下游回购(即从上游回收分支),所有这些都有可能处理重复的提交。

同样,对于“数据stream”类比,在DVCS中,一个错误的命令“上游”可能会在下游产生“ 连锁效应 ”。


注意:这不限于数据。
它也适用于参数 ,因为git命令(如“瓷器”命令)经常在内部调用其他git命令(“pipe道”命令)。 请参阅rev-parse手册页 :

许多git瓷器命令会混合使用标志(即以“ - ”开始的参数),以及它们在内部使用的基础git rev-list命令的参数以及它们在git rev-list下游使用的其他命令的标志和参数 。 这个命令用来区分它们。

上游(如相关)跟踪

上游这个术语在GIT工具套件中也有一些明确的含义,特别是跟踪

例如 :

  $git rev-list --count --left-right "@{upstream}"...HEAD >4 12 

将打印当前工作分支后面(左)和前面(右)相对于当前正在跟踪该本地分支的远程分支如果有的话 )的提交数(最后一个caching值)。 它会打印一个错误信息,否则:

  >error: No upstream branch found for '' 
  • 正如已经说过的,你可以有一个本地仓库的远程数据库,例如,如果你从github分发一个仓库,然后发出一个“pull request”,你肯定至less有两个: origin (你的分叉回购在github上)和upstream (你从github分叉的回购)。 这些只是可互换的名称,只有'git @ …'url标识它们。

您的.git/config读取:

  [remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = git@github.com:myusername/reponame.git [remote "upstream"] fetch = +refs/heads/*:refs/remotes/upstream/* url = git@github.com:authorname/reponame.git 
  • 另一方面,GIT的@ {upstream}含义是独一无二的:

它是' 远程'上的 分支” (如果有的话),它跟踪“本地存储库”上的“当前分支

当你发出一个没有参数的普通的git fetch / git pull ,它就是你读/取的分支。

比方说,想要设置远程分支的起点/主站作为您签出的本地主分支的跟踪分支。 只是问题:

  $ git branch --set-upstream master origin/master > Branch master set up to track remote branch master from origin. 

这在.git/config添加了2个参数:

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

现在尝试(提供'上游'远程有'dev'分支)

  $ git branch --set-upstream master upstream/dev > Branch master set up to track remote branch dev from upstream. 

.git/config现在读取:

  [branch "master"] remote = upstream merge = refs/heads/dev 

git-push(1)手册页码

  -u --set-upstream 

对于每个最新或成功推送的分支,添加无参数git-pull(1)和其他命令使用的上游(跟踪)引用。 有关更多信息,请参阅git-config(1)中的branch.<name>.merge

git-config(1)手册页码

  branch.<name>.merge 

branch.<name>.remote一起定义给定分支的上游分支。 它告诉git fetch / git pull / git rebase要合并的分支,还可能影响git push(请参阅push.default)。 \(…)

  branch.<name>.remote 

当在分支<名称>,它告诉git fetch和git推哪个远程从/ push到。 如果没有configuration远程,它默认为原点。 如果您不在任何分支上,也使用原点。

上游推(Gotcha)

看看git-config(1)手册页

  git config --global push.default upstream git config --global push.default tracking (deprecated) 

这是为了防止意外推到你尚未准备推送的分支。

上游被称为有害

还有另外一个“上游”的用法,其他人在这里回答的问题并没有涉及,即提到回购协议内的提交的亲子关系。 Pro Git书中的 Scott Chacon特别倾向于这一点,结果是不幸的。 不要模仿这种说话的方式。

例如,他说合并导致快速发生,这是因为

您合并的分支指向的提交直接位于提交的上游

他想说,提交B是提交A的唯一subprocess的唯一subprocess,因此要将B合并到A中,只需将参考A移动到指向提交B即可。为什么这个方向应该被称为“上游”而不是“下游”,或者为什么这种纯直线图的几何形状应该被描述为“直接上游”,完全不清楚,可能是任意的。 (当git-merge的man页面说“当前的分支头是命名提交的祖先”时,parsing这个关系的工作就更好了。这就是Chacon应该说的那样)。

事实上,Chacon本人似乎在稍后使用“下游”来表示完全一样的东西,当他谈到重写所有提交了删除提交的子提交时:

你必须重写6df76下的所有提交,从Git历史中完全删除这个文件

基本上他似乎没有任何清楚的概念,他提到的承诺历史随着时间的推移,“上游”和“下游”是什么意思。 那么这种用法是非正式的,不会被鼓励,因为这只是混乱。

很清楚,每一个承诺(除了一个)至less有一个父母,父母的父母是祖先。 而在另一个方向,犯有子女和后代。 这是接受的术语,并且明确地描述了图的方向性,所以当你想要描述提交图的graphics几何中的提交是如何相互关联的时候,这就是说话的方式。 在这种情况下不要松散地使用“上游”或“下游”。

[附加说明:我一直在思考上面引用的第一个Chacon句子和git-merge man页面之间的关系,前者可能是基于对后者的误解。 手册页描述了使用“上游”是合法的情况:快速转发通常发生在“您正在跟踪上游存储库,您没有提交本地更改,现在您想更新到更新上游修订“。 所以也许Chacon使用“上游”,因为他在手册页看到它。 但在手册页中有一个远程存储库; Chacon引用的快速转发示例中没有远程存储库,只有几个本地创build的分支机构。

这是一个非正式的术语。

就Git而言,每个其他的存储库都只是一个远程的。

一般来说,上游是您从(起源)克隆的地方。 下游是任何将您的作品与其他作品进行整合的项目。

这些条款不限于Git仓库。

例如,Ubuntu是Debian的衍生产品,所以Debian是Ubuntu的上游。