为什么我必须"git push --set-upstream origin <branch>"?

jww*_*jww 92 git branch

我创建了一个用于测试Solaris和Sun Studio的本地分支.然后我把分支推到了上游.提交更改并尝试推送更改后:

$ git commit blake2.cpp -m "Add workaround for missing _mm_set_epi64x"
[solaris 7ad22ff] Add workaround for missing _mm_set_epi64x
 1 file changed, 5 insertions(+)
$ git push
fatal: The current branch solaris has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin solaris
Run Code Online (Sandbox Code Playgroud)

为什么我要为此做一些特别的事情?

是否有任何合理的用例,有人会创建<branch>,推<branch>送到远程,然后声称提交<branch>不应该是<branch>


我在Stack Overflow上关注了这个问题和答案:将一个新的本地分支推送到远程Git存储库并跟踪它.我猜它是另一个不完整或错误接受答案的例子.或者,它的另一个Git实例执行一项简单的任务并使其变得困难.


这是不同机器上的视图.分支显然存在,因此它被创建并推送:

$ git branch -a
  alignas
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/alignas
  remotes/origin/arm-neon
  remotes/origin/det-sig
  remotes/origin/master
  remotes/origin/solaris
Run Code Online (Sandbox Code Playgroud)

tor*_*rek 200

TL; DR: git branch --set-upstream-to origin/solaris


这个问题的答案你问哪个,我会改写一个部位为"我必须设置一个上游" -is的问题:不,你不具备设置上游可言.

但是,如果当前分支没有上游,Git会更改其行为git push,也会更改其他命令.

这里完整的推送故事漫长而乏味,可以追溯到Git 1.5版之前的历史.为了缩短它,git push实施得很差.1 从Git 2.0版开始,Git现在有一个拼写的配置旋钮push.default,现在默认为simple.对于2.0之前和之后的几个版本的Git,每次你跑步时git push,Git会发出很多噪音试图说服你设置push.default只是git push为了闭嘴.

你没有提到你正在运行哪个版本的Git,也没有提到你是否已经配置push.default,所以我们必须猜测.我的猜测是你正在使用Git版本2点的东西,并且你已经设置push.defaultsimple让它闭嘴.正是你有哪些的Git版本,以及如果任何你已经push.default设定,的事情,因为那漫长而枯燥的历史,但最终的事实,你要还来自另一个Git的投诉表明你的Git 配置为避免过去的错误之一.

什么是上游?

上游仅仅是另一个分支名称,通常是一个远程跟踪分支,具有(常规,本地)分支相关联.

每个分支都可以选择具有一(1)个上游集.也就是说,每个分支都有一个上游,或者没有上游.没有分支可以有多个上游.

上游应该,但不一定是有效的分支(无论是远程跟踪还是本地类似).也就是说,如果当前分支B具有上游U,则应该工作.如果它不起作用 - 如果它抱怨U不存在 - 则大多数Git的行为就像上游根本没有设置一样.一些命令,例如,将显示上游设置,但将其标记为"已消失".origin/Bmastergit rev-parse U git branch -vv

上游有什么用?

如果您push.default设置为simpleupstream,则上游设置将生成git push,无需其他参数即可使用.

就是这样 - 这就是它的全部功能git push.但这是相当重要的,因为git push是一个简单的拼写错误引起严重头痛的地方之一.

如果您push.default设置为nothing,, matchingcurrent设置上游什么都不做git push.

(所有这些假设您的Git版本至少为2.0.)

上游影响 git fetch

如果你git fetch没有额外的参数运行,Git 通过咨询当前分支的上游来确定要从哪个远程获取.如果上游是远程跟踪分支,Git从该远程获取.(如果上游未设置或是本地分支,Git会尝试获取origin.)

上游影响git merge也是git rebase如此

如果你运行git mergegit rebase没有其他参数,Git使用当前分支的上游.因此它缩短了这两个命令的使用.

上游影响 git pull

你永远不应该使用2git pull,但是如果你这样做,git pull使用上游设置来确定要从中获取哪个远程,然后使用哪个分支进行合并或变换.也就是说,git pull做同样的事情 - git fetch因为它实际上运行 git fetch - 然后做同样的事情git merge或者git rebase,因为它实际上运行 git mergegit rebase.

(你通常应该手动执行这两个步骤,至少在你完全了解Git时,当任何一个步骤失败时,他们最终将会识别出错误并知道如何处理它.)

上游影响 git status

这实际上可能是最重要的.一旦有了上游集,git status就可以在提交方面报告当前分支与其上游之间的差异.

如果,正常情况下,您在B上游设置为分支,并且您运行,您将立即看到您是否有可以推送的提交,和/或提交您可以合并或重新绑定.origin/Bgit status

这是因为git status运行:

  • git rev-list --count @{u}..HEAD:你有多少提交B没有?origin/B
  • git rev-list --count HEAD..@{u}:你有多少提交没有?origin/BB

设置上游为您提供所有这些功能.

为什么master有一个上游设置?

当您首次从某个远程克隆时,使用:

$ git clone git://some.host/path/to/repo.git
Run Code Online (Sandbox Code Playgroud)

或类似的,Git所做的最后一步基本上是git checkout master.这将检查你的本地分支master-只有你没有拥有一个本地分支master.

另一方面,您确实有一个名为的远程跟踪分支origin/master,因为您只是克隆它.

Git的猜测,你一定意味:"让我一个新的地方master,它指向同一个commit,远程跟踪origin/master,并且,当你在它,设置为上游masterorigin/master."

对于您尚未拥有的每个分支都会发生这种情况git checkout.Git创建分支使其"跟踪"(具有上游)相应的远程跟踪分支.

但是,这并不为工作的新分支,即分支没有远程跟踪分支.

如果您创建一个分支:

$ git checkout -b solaris
Run Code Online (Sandbox Code Playgroud)

到目前为止,没有origin/solaris.您的本地solaris 无法跟踪远程跟踪分支,origin/solaris因为它不存在.

当你第一次推新分支时:

$ git push origin solaris
Run Code Online (Sandbox Code Playgroud)

造成 solarisorigin,因此也创造origin/solaris你自己的Git仓库.但为时已晚:你已经有一个地方solaris没有的上游.3

不应该Git只是设置,现在,作为上游自动?

大概.请参阅"执行不力"和脚注1.这是很难改变现在:有几百万4使用Git和一些可能取决于其当前的行为脚本.更改行为需要新的主要版本,nag-ware强制您设置一些配置字段,依此类推.简而言之,Git是其自身成功的牺牲品:无论它在其中存在什么样的错误,今天只有在变化大部分是隐形的,明显更好的或随着时间的推移缓慢完成时才能得到修复.

事实是,它不是今天,除非你使用--set-upstream-u期间git push.这就是消息告诉你的.

你没必要这样做.好吧,正如我们上面提到的,你根本不必这样做,但是假设你想要一个上游.你已经创建的分支solarisorigin,通过早期的推动,并作为你的git branch输出显示,你已经 origin/solaris在本地资源库.

你只是没有将它设置为上游solaris.

要立即设置,而不是在第一次按下时使用git branch --set-upstream-to.所述--set-upstream-to子命令采用名称的任何现有分支的,如origin/solaris,并设定当前分支的上游到其他分支.

就是这样 - 它就是这样 - 但它具有上述所有这些含义.这意味着你可以运行git fetch,然后环顾四周,然后运行git mergegit rebase酌情运行,然后进行新的提交并运行git push,而不需要额外的烦恼.


1公平地说,当时尚不清楚初始实施是否容易出错.只有当每个新用户每次都犯同样的错误时,这才会变得清晰.它现在"不那么差",这并不是说"好".

2 "从不"有点强,但我发现Git新手在分离步骤时会更好地理解事情,特别是当我能向他们展示git fetch实际做的事情时,他们可以看到接下来会做什么git merge或者git rebase做什么.

3如果你运行第一个 git push as git push -u origin solaris-ie,如果添加-u标志 - origin/solaris如果(并且仅当)推送成功,Git将设置为当前分支的上游.所以你应该-u在第一次推动时提供.实际上,您可以在以后的任何推送中提供它,并且它将在该点设置或更改上游.但git branch --set-upstream-to如果你忘了,我认为会更容易.

4无论如何,通过奥斯汀权力/邪恶博士的方法测量,简单地说"一个MILLLL-YUN".

  • 请注意,这是可配置的。如果您执行git config --add push.default current,则git push将在必要时自动在远程仓库中创建分支。 (5认同)
  • @torek - 谢谢.你的答案太棒了; 经过深思熟虑,结构合理,信息量极大.:-) (4认同)
  • 如果常见的情况是{创建分支/推送分支/使用分支},那么不应该是[将新的本地分支推送到远程 Git 存储库并进行跟踪](http://stackoverflow.com/a /6232535/608639) 是真正有效的东西吗?如果有人想要{创建分支/推送分支/不使用分支},那么他们不应该做一些特别的事情,比如`--set-upstream /dev/null`吗?为什么将负担推到普通案件上?我真的不明白其中一些工程和可用性决策。 (3认同)
  • @VonC:对,这就是 `git push -u` 的重点,但看起来 `git push -u` 应该是默认值,或者至少是默认值,如果没有上游 *还没有*,并且应该有一个 `git push --no-set-upstream` 当当前没有上游并且你想保持这种方式时(无论出于什么不可理解的原因:-))。 (2认同)
  • “您一直这样问问题,因为我认为您已将Git取消为“确实令人讨厌”。” 请保持这种猜测。我遇到了这个问题,因为我也一直在问自己这些问题。我不是世界上最好的UX设计人员,但是即使我也意识到,在这种特定情况下,默认行为可能会更好。 (2认同)

box*_*xed 97

您可以配置 git 自动执行此操作:

git config --global push.default current

根据我的经验,99% 的情况下这都是你想要的。


Oum*_*ima 27

使用 Git 2.37.0 版本,无需使用 --set-upstream origin。启用push.autoSetupRemote后,您可以使用以下命令直接使用git推送:

git config --global --add --bool push.autoSetupRemote true
Run Code Online (Sandbox Code Playgroud)

来源:James Ide 的推文

希望这可以帮助!


小智 14

我的理解是-uor--set-upstream允许您为您所在的分支指定上游(远程)存储库,这样下次运行时git push,您甚至不必指定远程存储库。

推送并将上游(远程)存储库设置为源:

$ git push -u origin
Run Code Online (Sandbox Code Playgroud)

下次推送时,您不必指定远程存储库:

$ git push
Run Code Online (Sandbox Code Playgroud)


Elp*_*Kay 11

一个基本上完整的命令就像git push <remote> <local_ref>:<remote_ref>.如果你只运行git push,git不知道该怎么做,除非你做了一些配置,帮助git做出决定.在git repo中,我们可以设置多个遥控器.我们也可以将本地参考推送到任何远程参考.完整命令是最直接的推动方式.如果要键入较少的单词,则必须先进行配置,如--set-upstream.


Ols*_*nsk 9

tl;dr 如果你不想考虑这个但也不想修改你的配置:

git push --set-upstream origin $(git branch --show-current)


Ada*_*dam 5


git push origin <branch>
和之间的区别
git push --set-upstream origin <branch>
是它们都可以很好地推送到远程存储库,但是在您拉出时您会注意到差异。

如果您这样做:
git push origin <branch>
拉动时,您必须:
git pull origin <branch>

但是如果您这样做:
git push --set-upstream origin <branch>
那么,在拉动时,您只需要做:
git pull

因此,添加--set-upstream允许不必指定每次执行都要拉出的分支git pull

  • @FrankPuck这是Git,它声称可以离线使用,但是如果没有Google或SO,一旦你离开“踩过的路径”就不可能使用。简单解释一下:`git push`中的`--set-upstream`(相对于`gitbranch`和`--set-upstream-to`)就是`-b`对于`git checkout`的意义(相对于`git checkout`) `git Branch` 或现在的 `git switch -c`)。这自始至终都是疯狂的,你不应该期待任何更少的事情。当然,使用“git push set-upstream”时,您需要指定“remotebranch”,而使用“gitbranch--set-upstream-to”时,您需要使用“remote/branch”(也称为 commreftreeish)。 (4认同)
  • @FrankPuck 两者之间的区别在于 git 被创建为一个分布式版本控制系统,没有像 CVS 和 SVN 这样的中央事实来源。GitHub 等集中式存储库的激增已将 git 变成了集中式 vcs 模型的副本。这就是推送行为不包括单个上游的原因。您应该能够将更改推送到任何需要它的存储库。朋友的、中央服务器、您拥有的另一台机器等。这是一种共享变更集的方式,而不是集中版本的方式。 (4认同)
  • 两个版本的“git Push”之间的区别,我不知道为什么我想要/需要使用它们。无意义! (2认同)

Dan*_*she 5

-u 标志指定您要将本地分支链接到上游分支。如果上游分支不存在,这也将创建一个上游分支。这些答案都没有涵盖我是如何做的(以完整的形式),所以这里是:

git push -u origin <your-local-branch-name>
Run Code Online (Sandbox Code Playgroud)

所以如果你当地的分店名称是咖啡

git push -u origin coffee
Run Code Online (Sandbox Code Playgroud)

  • `-u` 只是 `--set-upstream` 的快捷方式。尽管有人投票,但根本不清楚这个答案如何远程回答OP的问题。在“我如何做”食谱领域,下面的盒装答案更有用,因为它避免了每次都输入样板文件。 (5认同)