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


901

我开始玩Git,遇到过“上游”和“下游”这两个术语。我以前看过这些,但从未完全了解它们。这些术语在SCM(软件配置管理工具)和源代码的上下文中是什么意思?


13
git中上游/下游有两种不同的上下文:远程和时间/历史记录。相对于远程站点的上游/下游,下游回购将从上游回购中拉出(更改将自然流向下游)。关于时间/历史的上游/下游可能会造成混淆,因为时间的上游意味着历史的下游,反之亦然(家谱术语在这里工作得更好-父母/祖先/子女/后代)。
charlesreid1


Answers:


703

在源代码管理方面,从存储库复制(克隆,签出等)时,您处于“ 下游 ”状态。信息流向您的下游。

进行更改时,通常希望将它们发送回“ 上游 ”,以便它们将其发送到该存储库中,以便从同一源提取信息的每个人都可以进行所有相同的更改。这主要是每个人如何协调工作的社会问题,而不是源代码控制的技术要求。您希望将更改纳入主项目,以免跟踪不同的开发路线。

有时,您会读到有关将更改提交到“上游”的程序包或发行经理(人员,而不是工具)的信息。这通常意味着他们必须调整原始来源,以便可以为其系统创建一个程序包。他们不想继续进行这些更改,因此,如果将它们“上游”发送到原始来源,则他们不必在下一发行版中处理相同的问题。


115
“下载”和“上传”是动词。“上游”和“下游”描述相对位置。
brian d foy 2015年

2
我要说的上游和下游是形容词
CRT

8
它们用作修饰语时是形容词,但这些术语通常用作名词。
brian d foy

2
根据上下文
@

1
这主要是一个社会问题,而不是技术要求。那么,为什么有一个选项-u一样git push --set-upstream origin master,如果它不是一个技术要求?我们可以push -u origin或不可以push origin,所以这是一项技术要求。但是有什么区别呢?
格林

249

当您在git tag手册页中阅读时:

git的一个重要方面是它是分布式的,并且很大程度上是分布式的,这意味着系统中没有固有的“上游”或“下游”。

,仅表示没有绝对上游回购或下游回购。
这些概念始终是两个仓库之间的相对关系,并取决于数据流的方式:

如果“ yourRepo”已声明“ otherRepo”为远程数据库,则

  • 您正在从上游拉 “otherRepo”(“otherRepo”是“上游你”,你是“下游用于 otherRepo”)。
  • 您正在向上游推送(“ otherRepo”仍然是“上游”,现在信息返回到该上游)。

注意“ from”和“ for”:您不仅是“下游”,而且是“ from / for ”的下游,因此是相对方面。


DVCS(分布式版本控制系统)的缺点是:您不知道下游到底是什么,除了您自己的仓库(相对于已声明的远程仓库)之外。

  • 您知道上游是什么(您从中提取或推动到的存储库)
  • 您不知道下游是什么构成的(其他回购从您的回购中拉出或推送到您的回购中)。

基本上:

在“ 数据流 ”方面,您的存储库位于来自上游存储库(“从...拉出”)并返回(相同或其他)上游存储库(“推送至”)的流的底部(“下游”) )。


您可以在git-rebase手册页中看到带有“从UPSTREAM REBASE进行恢复”段落的插图:

这意味着您要从发生了基础更改的“上游”存储库中拉出,并且您(“下游”存储库)被结果卡住了(很多重复的提交,因为分支基于上游的分支重新创建了与您相同的分支的提交)本地)。

这很不好,因为对于一个“上游”存储库,可能有许多下游存储库(即,从具有上游存储库的存储库,通过重新定位的分支),所有这些存储库都可能处理重复的提交。

再次,与“数据流”类比,在DVCS中,一个错误的命令“上游”可能对下游产生“ 波纹效应 ”。


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

许多git命令混合使用标志(即以破折号' -' 开头的参数)和表示git rev-list内部使用的基本命令的参数,以及用于下游的其他命令的标志和参数的混合git rev-list。此命令用于区分它们。


15
从拉动上游,而你推到上游。推送到下游听起来对我来说是非常错误的
knittl'5

1
@knittl:你是对的。我改写了我的答案,以更好地说明“上游”存储库相对于您自己的本地(和“下游”)存储库的作用。
VonC'5

85

上游(与之相关)跟踪

对于GIT工具套件,上游一词也具有明确的含义,尤其是相对于跟踪

例如 :

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

相对于该本地分支当前正在跟踪的远程分支如果有),将打印(当前的分支的后面(左侧)和前面(右侧))提交的数量(最后缓存的值)。否则将显示错误消息:

    >error: No upstream branch found for ''
  • 如前所述,一个本地存储库可能有任意数量的远程服务器,例如,如果您从github派生一个存储库,然后发出“拉取请求”,则您肯定至少有两个:(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
  • 另一方面,@ {upstream}对GIT的含义是唯一的:

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

这是每当您发出无参数的git fetch/ 时从中获取/拉取的分支git pull

假设要将远程分支的原始/主节点设置为已签出的本地主分支的跟踪分支。只是问题:

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

这会在中添加2个参数.git/config

   [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)和其他命令使用。有关更多信息,请参见branch.<name>.mergegit-config(1)。

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从哪个远程获取/推送到。如果未配置任何远程服务器,则默认为源。如果您不在任何分支上,也将使用origin。

上游推(Gotcha)

看看git-config(1)手册页

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

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


4
git branch --help截至2018年的节选:As this option had confusing syntax, it is no longer supported. Please use --track or --set-upstream-to instead.
zezollo

59

这是一些非正式的术语。

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

一般来说,上游是您从中克隆的(来源)。下游是将您的工作与其他工作集成在一起的任何项目。

这些术语不限于Git存储库。

例如,Ubuntu是Debian的衍生产品,因此Debian在Ubuntu的上游。


51

上游被称为有害

a,还有“上游”的另一种用法,这里的其他答案都没有得到,即是指回购中提交的父子关系。Pro Git书中的 Scott Chacon 尤其容易出现这种情况,结果很不幸。不要模仿这种说话方式。

例如,他说合并导致快速前进,这是因为

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

他想说提交B是提交A的唯一子项中...的唯一子项的唯一子项,因此要将B合并到A中,只需将引用A指向提交B即可。应该将其称为“上游”而不是“下游”,或者为什么应该在“直接上游”描述这种纯直线图的几何形状,这是完全不清楚的,并且可能是任意的。(的手册页git-merge在解释这种关系时做得更好,当它说“当前分支头是指定提交的祖先。”这就是Chacon应该说的那种话。)

的确,当Chacon谈到重写已删除的提交的所有子提交时,他自己似乎后来使用“下游”一词是完全相同的:

您必须重写6df76下游的所有提交,才能从Git历史记录中完全删除此文件

基本上,当谈到一段时间内的提交历史时,他似乎并不清楚其对“上游”和“下游”的含义。因此,这种使用是非正式的,不应鼓励,因为这很令人困惑。

完全清楚的是,每一项承诺(除一项承诺外)都至少有一位父母,因此父母的父母就是祖先;在另一个方向上,提交有孩子和后代。这是公认的术语,并且明确描述了图的方向性,因此,当您要描述回购的图几何中的提交如何相互关联时,这就是一种交谈的方式。在这种情况下,请勿宽松地使用“上游”或“下游”。

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


14
git-rebase手册页也遭受这种重载:在重新定基础之前检出的提交称为“上游”。这也可能会影响Chacon的使用。
2014年

@out很奇怪-在git html文档中,在重新定基前签出的分支称为<branch>
Jesper Matthiesen

好点子。在某处收集通用的“ git-术语”会有所帮助。特别是对于新手(或对git有贡献的ppl)。本来可以节省我很好的时间来习惯git手册页的措辞。
SebNag


1
git-rebase文档中来到这里是因为我完全困惑为什么在这里将提交引用称为“上游”(实际上,我对此感到怀疑,因为我之前从未见过该术语)。感谢@outis和@matt整理了一切!
Borek Bernard
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.