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

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

答案

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

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

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

当您阅读git tag手册页时

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

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

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

  • 要从上游 “otherRepo” (“otherRepo” 是 “ 你上游”,而你 “ otherRepo 下游”)。
  • 您正在推向上游 (“otherRepo” 仍然是 “上游”,现在信息返回到该位置)。

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


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

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

基本上:

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


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

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

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

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


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

许多 GIT 中 porcelainish 命令采取标志的混合物(即以短划线开始参数 “ - ”)和意味着底层参数git rev-list它们内部使用命令和标志和参数为他们所使用的下游的其它命令git rev-list 。此命令用于区分它们。

上游(与之相关)跟踪

术语 “ 上游”在 GIT 工具套件中也具有明确的含义,尤其是相对于跟踪

例如 :

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

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

>error: No upstream branch found for ''
  • 如前所述,一个本地存储库可能具有任意数量的远程服务器,例如,如果您从 github 上存储一个存储库,然后发出 “拉取请求”,则您肯定至少有两个: originorigin您的分叉存储库)在 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.

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

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

现在尝试(如果 “上游” 远程具有 “开发” 分支)

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

上游推(Gotcha)

看看git-config(1)手册页

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

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

这是一些非正式的术语。

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

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

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

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

上游被称为有害

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

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

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

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

的确,Chacon 自己似乎在稍后用 “下游” 来表示完全相同的意思,当他谈到重写已删除的提交的所有子提交时:

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

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

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

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