我已经开始使用 Git,遇到过 “上游” 和 “下游” 这两个术语。我以前看过这些,但从未完全了解它们。这些术语在 SCM( 软件配置管理工具)和源代码的上下文中是什么意思?
在源代码管理方面,从存储库进行复制(克隆,签出等)时,您处于 “ 下游 ” 状态。信息流向您的下游。
进行更改时,通常希望将它们发送回 “ 上游 ”,以便它们将其发送到该存储库中,以便从同一源提取信息的每个人都可以进行所有相同的更改。这主要是每个人如何协调工作的社会问题,而不是源代码控制的技术要求。您想将更改纳入主项目,以免跟踪不同的开发路线。
有时,您会读到关于将更改提交到 “上游” 的程序包或发行经理(人员,而不是工具)的信息。这通常意味着他们必须调整原始源,以便可以为其系统创建一个程序包。他们不想继续进行这些更改,因此,如果将它们 “上游” 发送到原始源,则他们不必在下一发行版中处理相同的问题。
当您阅读git tag
手册页时 :
git 的一个重要方面是它的分布式,并且在很大程度上分布意味着系统中没有固有的 “上游” 或 “下游”。
,仅表示没有绝对上游回购或下游回购。
这些概念始终是两个仓库之间的相对关系,并取决于数据流的方式:
如果 “yourRepo” 已声明 “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 ''
origin
( 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 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
-u --set-upstream
对于每个最新的或成功推送的分支,请添加上游(跟踪)引用,该引用由无参数 git-pull(1)和其他命令使用。有关更多信息,请参见 git-config(1)中的
branch.<name>.merge
。branch.<name>.merge
与
branch.<name>.remote
一起定义给定分支的上游分支。它告诉 git fetch / git pull / git rebase 合并哪个分支,并且还可能影响 git push(请参阅 push.default)。 \(...)branch.<name>.remote
在分支 <名称> 中时,它告诉 git fetch 和 git push 从哪个远程获取 / 推送到。如果未配置任何远程服务器,则默认为源。如果您不在任何分支上,也将使用 origin。
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 引用的快速转发示例中没有远程存储库,只有几个本地创建的分支。