我开始使用Git,并遇到了“upstream”和“downstream”这些术语。我以前见过这些词,但从未完全理解它们。在SCM(软件配置管理工具)和源代码方面,这些术语是什么意思呢?
我开始使用Git,并遇到了“upstream”和“downstream”这些术语。我以前见过这些词,但从未完全理解它们。在SCM(软件配置管理工具)和源代码方面,这些术语是什么意思呢?
在源代码控制方面,当你从仓库中复制(克隆、检出等)时,你处于下游。信息向你“下游”流动。
当你进行更改时,通常希望将其发送回“上游”,以便它们进入仓库,这样每个人从相同的源码中拉取都会使用相同的更改。这主要是一个社交问题,涉及如何协调工作,而不是源代码控制的技术要求。你需要将自己的更改合并到主项目中,这样就不需要跟踪分支发展路线。
有时候,你会看到软件包或发行版管理者(指人员,而非工具)谈论将更改提交给“上游”。这通常意味着他们必须调整原始代码,以便为其系统创建软件包。他们不想继续进行这些更改,因此如果将它们发送给原始来源,则在下一个版本中就不必处理相同的问题。
git tag
man page 时,会看到以下内容:
这意味着简单来说,并没有绝对的上游或下游仓库存在。这些概念总是相对于两个仓库并取决于数据流的方式:Git 的一个重要特点是它是分布式的,而且作为分布式系统,在系统中不存在固有的“上游”或“下游”。
在“数据流”的术语中,你的仓库处于底部(“下游”),来自上游仓库的流向它(“拉取”),然后再返回(相同或其他)上游仓库(“推送”)。
git-rebase
手册页面中看到一个示例,其中包含“RECOVERING FROM UPSTREAM REBASE”段落:
这意味着您正在从发生rebase的“upstream” repo中拉取,并且您(即“downstream” repo)被卡在了后果中(因为分支在“upstream”重新创建了您本地具有相同分支的提交而导致了许多重复提交)。rev-parse
手册页面:
许多Git porcelainish命令使用混合标志(即以破折号“
-
”开头的参数)和参数,这些参数用于底层的git rev-list
命令,它们在内部使用并且包括用于其他downstream命令的标志和参数。此命令用于区分它们。
术语上游在GIT工具套件中也有一些明确的含义,特别是相对于跟踪而言。
例如:
$git rev-list --count --left-right "@{upstream}"...HEAD >4 12
will print (the last cached value of) the number of commits behind (left) and ahead (right) of your current working branch, relative to the (if any) currently tracking remote branch for this local branch. It will print an error message otherwise:
>error: No upstream branch found for ''
origin
(在 Github 上的您 fork 的仓库)和 upstream
(您从中 fork 的 Github 上的仓库)。这些只是可互换的名称,只有 'git@...' url 才能识别它们。Your
.git/config
reads :[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
时从中获取/拉取的分支。
假设您想将远程分支origin/master设置为您已检出的本地master分支的跟踪分支。只需执行以下操作:
$ git branch --set-upstream master origin/master > Branch master set up to track remote branch master from origin.
This adds 2 parameters in
.git/config
:
[branch "master"] remote = origin merge = refs/heads/master
now try (provided 'upstream' remote has a 'dev' branch)
$ git branch --set-upstream master upstream/dev > Branch master set up to track remote branch dev from upstream.
.git/config
now reads:
[branch "master"] remote = upstream merge = refs/heads/dev
-u --set-upstream
For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands. For more information, see
branch.<name>.merge
in git-config(1).branch.<name>.merge
Defines, together with
branch.<name>.remote
, the upstream branch for the given branch. It tells git fetch/git pull/git rebase which branch to merge and can also affect git push (see push.default). \ (...)branch.<name>.remote
When in branch < name >, it tells git fetch and git push which remote to fetch from/push to. It defaults to origin if no remote is configured. origin is also used if you are not on any branch.
git config --global push.default upstream git config --global push.default tracking (deprecated)
This is to prevent accidental pushes to branches which you’re not ready to push yet.
这是一些非正式的术语。
就 Git 而言,每个其他的代码库都只是一个远程仓库。
通常而言,上游是你从哪里克隆的(即源头)。下游是任何一个将你的工作与其他工作集成起来的项目。
这些术语并不局限于 Git 代码库。
例如,Ubuntu 是 Debian 的一个衍生版,因此 Debian 对于 Ubuntu 来说就是上游。
很遗憾,这里的其他答案并没有涉及到“upstream”另一种用法,即指代仓库内提交记录的父子关系。Scott Chacon在 Pro Git 书籍 中经常使用此用法,结果是不幸的。不要模仿这种说话方式。
例如,他说合并导致快进时会发生这种情况,是因为:
你要合并的分支所指向的提交与你当前的提交直接上游
他想表达的意思是提交B是提交A的唯一子代的唯一子代的...的唯一子代,所以将B合并到A中只需移动A引用指向提交B即可。为什么应该将此方向称为“上游”,而不是“下游”,或者为什么这样纯粹的直线图形的几何应该被称为“直接上游”,完全不清楚,可能是任意的。(当说“当前分支头是指定提交的祖先”时,git-merge
手册做得更好。这就是Chacon应该说的内容。)
事实上,当他谈到重写删除提交后所有子提交时,Chacon似乎在后面使用“下游”来完全指代同样的意思:
您必须重写从6df76开始的所有下游提交,以完全从Git历史记录中删除此文件
基本上,他似乎没有任何清晰的想法,关于引用提交历史的时间轴时“上游”和“下游”的含义。这种用法是非正式的,不应鼓励,因为它只会造成混乱。
很明显,每一个提交(除了一个)都至少有一个父节点,而父节点的父节点因此成为祖先;反过来,提交也有子节点和后代。这是公认的术语,并清楚地描述了图形内各个提交之间的关系方向,因此在描绘代码库中提交之间相互关联时,应该使用这种方式。不要在这种情况下松散使用"上游(upstream)"或"下游(downstream)"。
[额外说明:我一直在思考Chacon所引用的第一句话与git-merge
手册之间的关系,我发现前者可能基于对后者的误解。手册确实描述了一种情况,在这种情况下使用"上游(upstream)"是合理的:当"您正在跟踪上游存储库,没有提交本地更改,现在想要更新到较新的上游修订版本"的时候,通常会发生快速前进。所以,也许Chacon之所以使用"upstream"是因为他在这里看到了它。但在手册中,有一个远程存储库;在Chacon引用的快速前进示例中不存在远程存储库,只有几个本地创建的分支。]
<branch>
。 - Jesper Matthiesengit-rebase
文档中被称为“upstream”,所以我从那里来到这里(事实上,我还怀疑自己是否之前看过这个术语)。感谢@outis和@matt澄清了事情! - Borek BernardProject B
fork了Project A
,并且Project C
又fork了Project B
。Project A
是上游项目。
Project B
是相对于Project A
的下游项目。
Project B
是相对于Project C
的上游项目。
Project C
是相对于Project B
的下游项目。Pull requests
)。