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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37770467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:16:01  来源:igfitidea点击:

Why do I have to "git push --set-upstream origin <branch>"?

gitbranch

提问by jww

I created a local branch for testing Solaris and Sun Studio. I then pushed the branch upstream. After committing a change and attempting to push the changes:

我创建了一个本地分支来测试 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

Why do I have to do something special for this?

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

Is there any reasonable use case where someone would create <branch>, push the <branch>to remote, and then claim a commit on <branch>is not supposed to be for <branch>?

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



I followed this question and answer on Stack Overflow: Push a new local branch to a remote Git repository and track it too. I'm guessing its another instance of a incomplete or wrong accepted answer. Or, its another instance of Git taking a simple task and making it difficult.

我在 Stack Overflow 上关注了这个问题和答案:Push a new local branch to a remote Git repository and tracking it too。我猜这是另一个不完整或错误的接受答案的例子。或者,它是 Git 执行简单任务并使其变得困难的另一个实例。



Here's the view on a different machine. The branch clearly exists, so it was created and pushed:

这是另一台机器上的视图。该分支显然存在,因此它被创建和推送:

$ 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

回答by torek

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

特尔;博士: git branch --set-upstream-to origin/solaris



The answer to the question you asked—which I'll rephrase a bit as "do I have to set an upstream"—is: no, you don't haveto set an upstream at all.

这个问题的答案你问哪个,我会改写一个部位为“我要设置一个上游” -is的问题:不,你不具备在所有设置的上游。

If you do not have upstream for the current branch, however, Git changes its behavior on git push, and on other commands as well.

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

The complete push story here is long and boring and goes back in history to before Git version 1.5. To shorten it a whole lot, git pushwas implemented poorly.1As of Git version 2.0, Git now has a configuration knob spelled push.defaultwhich now defaults to simple. For several versions of Git before and after 2.0, every time you ran git push, Git would spew lots of noise trying to convince you to set push.defaultjust to get git pushto shut up.

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

You do not mention which version of Git you are running, nor whether you have configured push.default, so we must guess. My guess is that you are using Git version 2-point-something, and that you have set push.defaultto simpleto get it to shut up. Precisely which version of Git you have, and what if anything you have push.defaultset to, doesmatter, due to that long and boring history, but in the end, the fact that you're getting yet another complaint from Git indicates that your Git isconfigured to avoid one of the mistakes from the past.

你没有提到你运行的是哪个版本的 Git,也没有提到你是否配置了push.default,所以我们必须猜测。我的猜测是,你正在使用的Git版本2点东西,并且已设置push.defaultsimple让它闭嘴。确切地说,您拥有哪个版本的 Git,如果您push.default设置了任何内容,这确实很重要,因为那段漫长而无聊的历史,但最终,您收到来自 Git 的另一个抱怨的事实表明您的 Git配置以避免过去的错误之一。

What is an upstream?

什么是上游?

An upstreamis simply another branch name, usually a remote-tracking branch, associated with a (regular, local) branch.

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

Every branch has the option of having one (1) upstream set. That is, every branch either has an upstream, or does not have an upstream. No branch can have more than one upstream.

每个分支都可以选择拥有一 (1) 个上游集。也就是说,每个分支要么有上游,要么没有上游。任何分支都不能有多个上游。

The upstream should, but does not have to be, a valid branch (whether remote-tracking like origin/Bor local like master). That is, if the current branch Bhas upstream U, git rev-parse Ushouldwork. If it does not work—if it complains that Udoes not exist—then most of Git acts as though the upstream is not set at all. A few commands, like git branch -vv, will show the upstream setting but mark it as "gone".

上游应该,但不一定是,一个有效的分支(无论是远程跟踪之类的还是本地之类的)。也就是说,如果当前分支B有上游U应该可以工作。如果它不起作用——如果它抱怨U不存在——那么大多数 Git 就像上游根本没有设置一样。一些命令,如,将显示上游设置,但将其标记为“gone”。origin/Bmastergit rev-parse Ugit branch -vv

What good is an upstream?

上游有什么好处?

If your push.defaultis set to simpleor upstream, the upstream setting will make git push, used with no additional arguments, just work.

如果您push.default设置为simpleor upstream,则上游设置将 make git push,无需额外参数即可使用。

That's it—that's all it does for git push. But that's fairly significant, since git pushis one of the places where a simple typo causes major headaches.

就是这样——这就是它为 所做的一切git push。但这相当重要,因为这git push是一个简单的错字导致严重头痛的地方之一。

If your push.defaultis set to nothing, matching, or current, setting an upstream does nothing at all for git push.

如果您push.default设置为nothing, matching, or current,则设置上游对git push.

(All of this assumes your Git version is at least 2.0.)

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

The upstream affects git fetch

上游影响 git fetch

If you run git fetchwith no additional arguments, Git figures out whichremote to fetch from by consulting the current branch's upstream. If the upstream is a remote-tracking branch, Git fetches from that remote. (If the upstream is not set or is a local branch, Git tries fetching origin.)

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

The upstream affects git mergeand git rebasetoo

上游影响git mergegit rebase

If you run git mergeor git rebasewith no additional arguments, Git uses the current branch's upstream. So it shortens the use of these two commands.

如果您运行git mergegit rebase没有附加参数,Git 将使用当前分支的上游。所以它缩短了这两个命令的使用。

The upstream affects git pull

上游影响 git pull

You should never2use git pullanyway, but if you do, git pulluses the upstream setting to figure out which remote to fetch from, and then which branch to merge or rebase with. That is, git pulldoes the same thing as git fetch—because it actually runsgit fetch—and then does the same thing as git mergeor git rebase, because it actually runsgit mergeor git rebase.

无论如何,您永远不应该使用2git pull,但是如果您这样做了,请git pull使用上游设置来确定要从哪个远程获取,然后与哪个分支合并或变基。也就是说,git pull做同样的事情——git fetch因为它实际上运行git fetch——然后做同样的事情git mergeor git rebase,因为它实际上运行git mergeor git rebase

(You should usually just do these two steps manually, at least until you know Git well enough that when either step fails, which they will eventually, you recognize what went wrong and know what to do about it.)

(你通常应该手动完成这两个步骤,至少在你足够了解 Git 之前,当任何一个步骤失败时,他们最终会发现哪里出了问题,并知道如何处理它。)

The upstream affects git status

上游影响 git status

This may actually be the most important. Once you have an upstream set, git statuscan report the difference between your current branch and its upstream, in terms of commits.

这实际上可能是最重要的。一旦你有一个上游集,git status就可以报告你当前分支与其上游之间的差异,就提交而言。

If, as is the normal case, you are on branch Bwith its upstream set to origin/B, and you run git status, you will immediately see whether you have commits you can push, and/or commits you can merge or rebase onto.

如果像正常情况一样,您在分支上B,其上游设置为,并且您运行,您将立即看到您是否有可以推送的提交,和/或可以合并或变基的提交。origin/Bgit status

This is because git statusruns:

这是因为git status运行:

  • git rev-list --count @{u}..HEAD: how many commits do you have on Bthat are not on origin/B?
  • git rev-list --count HEAD..@{u}: how many commits do you have on origin/Bthat are not on B?
  • git rev-list --count @{u}..HEAD:有多少提交你对B那些不上?origin/B
  • git rev-list --count HEAD..@{u}:有多少提交你对那些不上?origin/BB

Setting an upstream gives you all of these things.

设置上游为您提供了所有这些东西。

How come masteralready has an upstream set?

怎么master已经有上游集了?

When you first clone from some remote, using:

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

$ git clone git://some.host/path/to/repo.git

or similar, the last step Git does is, essentially, git checkout master. This checks out your local branch master—only you don't havea local branch master.

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

On the other hand, you dohave a remote-tracking branch named origin/master, because you just cloned it.

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

Git guesses that you must have meant: "make me a new local masterthat points to the same commit as remote-tracking origin/master, and, while you're at it, set the upstream for masterto origin/master."

Git 猜测您的意思一定是:“让我成为一个新的本地master,指向与 remote-tracking 相同的提交origin/master,并且,当您在此时,将上游设置为masterto origin/master。”

This happens for everybranch you git checkoutthat you do not already have. Git creates the branch andmakes it "track" (have as an upstream) the corresponding remote-tracking branch.

这发生在您还没有的每个分支上git checkout。Git 创建分支使其“跟踪”(作为上游)相应的远程跟踪分支。

But this doesn't work for newbranches, i.e., branches with no remote-tracking branch yet.

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

If you create a newbranch:

如果您创建一个分支:

$ git checkout -b solaris

there is, as yet, no origin/solaris. Your local solariscannottrack remote-tracking branch origin/solarisbecause it does not exist.

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

When you first push the new branch:

当您第一次推送新分支时:

$ git push origin solaris

that createssolarison origin, and hence also creates origin/solarisin your own Git repository. But it's too late: you already have a local solaristhat has no upstream.3

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

Shouldn't Git just set that, now, as the upstream automatically?

现在,Git 不应该自动将其设置为上游吗?

Probably. See "implemented poorly" and footnote 1. It's hard to change now: There are millions4of scripts that use Git and some may well depend on its current behavior. Changing the behavior requires a new major release, nag-ware to force you to set some configuration field, and so on. In short, Git is a victim of its own success: whatever mistakes it has in it, today, can only be fixed if the change is either mostly invisible, clearly-much-better, or done slowly over time.

大概。请参阅“执行不力”和脚注1。这是很难改变现在:有几百万4使用Git的脚本和一些可能取决于其当前行为。改变行为需要一个新的主要版本,nag-ware 强制你设置一些配置字段,等等。简而言之,Git 是其自身成功的受害者:今天,无论它有什么错误,只有在更改几乎不可见、明显好得多或随着时间的推移缓慢完成时,才能修复。

The fact is, it doesn't today, unlessyou use --set-upstreamor -uduring the git push. That's what the message is telling you.

事实是,今天不会,除非您使用--set-upstream-ugit push. 这就是消息告诉你的。

You don't have to do it like that. Well, as we noted above, you don't have to do it at all, but let's say you wantan upstream. You have already created branch solarison origin, through an earlier push, and as your git branchoutput shows, you already haveorigin/solarisin your local repository.

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

You just don't have it set as the upstream for solaris.

您只是没有将其设置为solaris.

To set it now, rather than during the first push, use git branch --set-upstream-to. The --set-upstream-tosub-command takes the name of any existing branch, such as origin/solaris, and sets the current branch's upstream to that other branch.

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

That's it—that's all it does—but it has all those implications noted above. It means you can just run git fetch, then look around, then run git mergeor git rebaseas appropriate, then make new commits and run git push, without a bunch of additional fussing-around.

就是这样 - 这就是它所做的 - 但它具有上述所有含义。这意味着您可以只运行git fetch,然后环顾四周,然后运行git mergegit rebase在适当的情况下,然后进行新的提交并运行git push,而无需额外的大惊小怪。



1To be fair, it was not clear back then that the initial implementation was error-prone. That only became clear when every new user made the same mistakes every time. It's now "less poor", which is not to say "great".

1公平地说,当时并不清楚最初的实施是否容易出错。只有当每个新用户每次都犯同样的错误时,这一点才变得清晰。现在是“不那么差”,也不是说“很棒”。

2"Never" is a bit strong, but I find that Git newbies understand things a lot better when I separate out the steps, especially when I can show them what git fetchactually did, and they can then see what git mergeor git rebasewill do next.

2“从不”有点强,但我发现当我将步骤分开时,Git 新手会更好地理解事情,尤其是当我可以向他们展示git fetch实际做了什么,然后他们可以看到下一步做什么git mergegit rebase将要做什么时。

3If you run your firstgit pushas git push -u origin solaris—i.e., if you add the -uflag—Git will set origin/solarisas the upstream for your current branch if (and only if) the push succeeds. So you should supply -uon the firstpush. In fact, you can supply it on any later push, and it will set or changethe upstream at that point. But I think git branch --set-upstream-tois easier, if you forgot.

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

4Measured by the Austin Powers / Dr Evil method of simply saying "one MILLLL-YUN", anyway.

4无论如何,通过 Austin Powers / Dr Evil 简单地说“one MILLLL-YUN”的方法来衡量。

回答by Adam

The difference between
git push origin <branch>
and
git push --set-upstream origin <branch>
is that they both push just fine to the remote repository, but it's when you pull that you notice the difference.


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

If you do:
git push origin <branch>
when pulling, you have to do:
git pull origin <branch>

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

But if you do:
git push --set-upstream origin <branch>
then, when pulling, you only have to do:
git pull

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

So adding in the --set-upstreamallows for not having to specify which branch that you want to pull from every single time that you do git pull.

因此,添加--set-upstream允许不必每次都指定要从哪个分支中提取git pull

回答by ElpieKay

A basically full command is like git push <remote> <local_ref>:<remote_ref>. If you run just git push, git does not know what to do exactly unless you have made some config that helps git to make a decision. In a git repo, we can setup multiple remotes. Also we can push a local ref to any remote ref. The full command is the most straightforward way to make a push. If you want to type fewer words, you have to config first, like --set-upstream.

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