我已经开始使用Git,并且遇到了术语“上游”和“下游”。我以前见过这些,但从来没有完全理解过。这些术语在scm(软件配置管理工具)和源代码的上下文中意味着什么?
在源代码控制方面,当您从存储库复制(克隆、签出等)时,您处于下游。信息向你“下游”流动。
当您进行更改时,您通常希望将它们发送回“上游”,以便它们进入存储库,以便从同一源提取的每个人都使用相同的更改。这主要是一个社会问题,即每个人如何协调他们的工作,而不是源代码控制的技术需求。您希望将更改放到主项目中,这样就不会跟踪不同的开发线。
有时您会读到包或发布管理人员(人,而不是工具)谈论向“上游”提交更改。这通常意味着他们必须调整原始源代码,以便为他们的系统创建一个包。他们不想继续做这些更改,所以如果他们将这些更改“上游”发送到原始源代码,他们就不应该在下一个版本中处理相同的问题。
这是一个非正式的术语。
就Git而言,每个其他存储库都只是一个远程存储库。
一般来说,上游是克隆的地方(源)。下游是将您的工作与其他工作集成在一起的任何项目。
这些术语并不局限于Git存储库。
例如,Ubuntu是Debian的衍生版本,所以Debian是Ubuntu的上游。
当你阅读git标签手册页时:
git的一个重要方面是它是分布式的,分布式很大程度上意味着系统中没有固有的“上游”或“下游”。
,这意味着没有绝对的上游回购或下游回购。 这些概念在两个回购之间总是相对的,取决于数据流动的方式:
如果"yourRepo"已声明"otherRepo"为远程repo,则:
你从上游“otherRepo”(“otherRepo”是“你的上游”,你是“otherRepo的下游”)。 你正在推送到上游(“otherRepo”仍然是“上游”,信息现在回到那里)。
注意"from"和"for":你不仅仅是"downstream",你是"downstream from/for",因此是相对方面。
DVCS(分布式版本控制系统)的扭曲是:除了您自己的回购相对于您已声明的远程回购之外,您不知道下游实际上是什么。
你知道什么是上游(你从回购中提取或推动) 你不知道下游是由什么构成的(其他回购从你的回购中拉或推)。
基本上:
就“数据流”而言,你的回购处于来自上游回购(“从”)并返回(相同或其他)上游回购(“推到”)的流的底部(“下游”)。
你可以在git-rebase手册页中看到一段“recovery FROM UPSTREAM REBASE”的说明:
这意味着你正在从一个发生了重基的“上游”回购中进行拉取,而你(“下游”回购)将会受到这样的后果(大量重复的提交,因为重基的上游分支重新创建了你在本地拥有的同一个分支的提交)。
这很糟糕,因为对于一个“上游”回购,可能会有许多下游回购(即从上游的回购中提取,带有重基分支),所有这些回购都可能要处理重复的提交。
同样,以“数据流”为类比,在DVCS中,一个错误的命令“上游”可能会对下游产生“涟漪效应”。
注:这不仅限于数据。 它也适用于参数,因为git命令(比如“瓷器”命令)经常在内部调用其他git命令(“管道”命令)。参见rev-parse手册页:
许多git瓷器命令混合使用了标志(即以“-”开头的参数)和用于底层git rev-list命令的参数,以及用于git rev-list下游的其他命令的标志和参数。该命令用于区分两者。
上游(与之相关)跟踪
对于GIT工具套件,术语上游也有一些明确的含义,特别是与跟踪相关的含义
例如:
$git rev-list——count——left-right "@{upstream}" 4 > 12 将打印当前工作分支后面(左)和前面(右)的提交数(最后的缓存值),相对于当前跟踪此本地分支的远程分支(如果有)。否则将打印错误消息: >错误:没有发现上游分支
正如已经说过的,你可能有一个本地存储库的任何数量的远程,例如,如果你从github分叉一个存储库,然后发出一个“拉请求”,你肯定至少有两个:起源(你在github上的分叉回购)和上游(你从github上分叉的回购)。这些只是可以互换的名字,只有“git@..”。' url标识它们。
你的。git/configreads: (远程“起源”) Fetch = +refs/heads/*:refs/remotes/origin/* Url = git@github.com:myusername/reponame.git (远程“上游”) Fetch = +refs/heads/*:refs/remotes/upstream/* Url = git@github.com:authorname/reponame.git
另一方面,@{upstream}对于GIT的意义是唯一的:
它是'said remote'上的'分支'(如果有的话),它跟踪'本地存储库'上的'当前分支'。 它是你每次调用纯git fetch/git pull时的fetch/pull分支,不带参数。
假设要将远程分支origin/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 git-push(1) Manual Page : -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). git-config(1) Manual Page : 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(1)手册页
Git配置——global push.default upstream Git配置——global push.default跟踪(已弃用) 这是为了防止意外地推到您还没有准备好推的分支。
上游称为有害
唉,“上游”还有另一种用法,这里的其他答案都没有提到,即指在一个repo中提交的父子关系。在Pro Git一书中,Scott Chacon特别容易出现这种情况,结果很不幸。不要模仿这种说话方式。
例如,他说合并导致了快进,这是因为
您所合并的分支所指向的提交是直接的 在提交的上游
He wants to say that commit B is the only child of the only child of ... of the only child of commit A, so to merge B into A it is sufficient to move the ref A to point to commit B. Why this direction should be called "upstream" rather than "downstream", or why the geometry of such a pure straight-line graph should be described "directly upstream", is completely unclear and probably arbitrary. (The man page for git-merge does a far better job of explaining this relationship when it says that "the current branch head is an ancestor of the named commit." That is the sort of thing Chacon should have said.)
事实上,Chacon自己在后面提到重写已删除提交的所有子提交时,似乎使用了“下游”来表达完全相同的意思:
必须重写从6df76开始的所有提交,才能完全删除 这个文件来自你的Git历史记录
基本上,在提到提交历史时,他似乎不清楚“上游”和“下游”是什么意思。因此,这种用法是非正式的,不鼓励使用,因为它会令人困惑。
很明显,每个commit(除了一个)都至少有一个父结点,因此父结点的父结点就是祖先;而在另一个方向上,承诺有子女和后代。这是公认的术语,并且明确地描述了图的方向性,所以当您想要描述在repo的图几何中提交如何相互关联时,这就是谈论的方式。在这种情况下,不要随意使用“上游”或“下游”。
[Additional note: I've been thinking about the relationship between the first Chacon sentence I cite above and the git-merge man page, and it occurs to me that the former may be based on a misunderstanding of the latter. The man page does go on to describe a situation where the use of "upstream" is legitimate: fast-forwarding often happens when "you are tracking an upstream repository, you have committed no local changes, and now you want to update to a newer upstream revision." So perhaps Chacon used "upstream" because he saw it here in the man page. But in the man page there is a remote repository; there is no remote repository in Chacon's cited example of fast-forwarding, just a couple of locally created branches.]
以河流为例,我们可以沿着资源逆流而上,直到找到源头(溪流或河流的源头)。
继续河的比喻,下游是河中水流动的方向。下坡。
所以,如果我分叉了某人的项目,我分叉的项目就是上游。我的叉子在下游。
如果有人分叉了我的分叉项目,那么我的分叉相对于我的项目的分叉成为上游。
我的叉子上的叉子顺流而下。
例如时间!
假设项目B衍生出项目A,项目C衍生出项目B。
那么项目A就是上游项目。
项目B是相对于项目A的下游项目。
B项目是相对于C项目的上游项目。
C项目是相对于B项目的下游项目。
生命的循环还在继续。
注意:请注意,这是开源项目中相当常见的开发风格,创建一个项目的分支,修复一个错误或在该分支中添加一个功能,然后向原始项目提交一个补丁。
还要注意,从“质量运动”和统计过程控制中得到的一个明显教训是,从源头解决质量问题的干预措施几乎总是比重复解决可以预防的问题更好的投资。所以请贡献补丁(发送Pull请求)。
推荐文章
- Visual Studio代码如何解决合并冲突与git?
- 无法推送到远程分支,无法解析到分支
- Git:如何将数据库重置为特定的提交?
- 如何在合并期间使用Git和命令行保存本地文件或远程文件?
- 能够用一个命令推到所有git遥控器?
- 重新基于Git合并提交
- 忽略已经签入目录的内容?
- 如何完全删除TFS绑定
- 哪些Eclipse文件属于版本控制?
- 如何从windows cmd保存git提交消息?
- (Mac) -bash: __git_ps1:命令未找到
- 如何删除多个已删除的文件在Git仓库
- 使用vimdiff查看所有' git diff '
- 如何拉特定的目录与git
- 本地存储库中的文件与源文件之间的差异