我创建了一个本地分支来测试 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
为什么我必须为此做一些特别的事情?
有人会创建
<branch>
是否有任何合理的用例? ,推<branch>
到远程,然后在 <branch>
上声明提交不应该用于 <branch>
?我在 Stack Overflow 上关注了这个问题和答案:Push a new local branch to a remote Git repository and track it too .我猜这是另一个不完整或错误的接受答案的例子。或者,它是 Git 执行简单任务并使其变得困难的另一个实例。
这是另一台机器上的 View 。该分支显然存在,因此它被创建和推送:
$ 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
最佳答案
TL;DR:git branch --set-upstream-to origin/solaris
您提出的问题的答案 - 我将稍微改写为“我是否必须设置上游” - 是:不,您根本不必设置上游。
但是,如果当前分支没有上游,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-point-something,并且您已将 push.default
设置为 simple
以使其关闭。确切地说,您拥有哪个版本的 Git,如果您将 push.default
设置为任何内容,这确实很重要,因为历史悠久而乏味,但最终,您收到来自 Git 的另一项投诉的事实表明您的 Git配置为避免过去的错误之一。
什么是上游?
上游只是另一个分支名称,通常是远程跟踪分支,与(常规,本地)分支相关联。
每个分支都可以选择拥有一 (1) 个上游集。也就是说,每个分支要么有上游,要么没有上游。任何分支都不能有多个上游。
上游应该但不一定是一个有效的分支(无论是像 origin/B
这样的远程跟踪还是像 master
这样的本地)。也就是说,如果当前分支 B 有上游 U,则 git rev-parse U
应该可以工作。如果它不起作用——如果它提示 U 不存在——那么大多数 Git 就好像上游根本没有设置一样。一些命令,例如 git branch -vv
,将显示上游设置,但将其标记为“gone”。
上游有什么好处?
如果您的 push.default
设置为 simple
或 upstream
,上游设置将使 git push
使用,无需额外参数,即可使用。
就是这样——这就是它为 git push
所做的一切。但这相当重要,因为 git push
是一个简单的错字导致严重头痛的地方之一。
如果您的 push.default
设置为 nothing
、 matching
或 current
,则设置上游对 git push
没有任何作用。
(所有这些都假设您的 Git 版本至少为 2.0。)
上游影响git fetch
如果您在没有其他参数的情况下运行 git fetch
,Git 会通过查询当前分支的上游来确定要从哪个远程获取。如果上游是远程跟踪分支,则 Git 从该远程获取。 (如果上游没有设置或者是本地分支,Git 会尝试获取 origin
。)
上游也会影响 git merge
和 git rebase
如果您在没有其他参数的情况下运行 git merge
或 git rebase
,Git 将使用当前分支的上游。所以它缩短了这两个命令的使用。
上游影响git pull
无论如何,您永远都不应该使用 git pull
,但是如果您这样做了,git pull
会使用上游设置来确定要从哪个远程获取数据,然后确定要与哪个分支 merge 或 rebase 。也就是说, git pull
和 git fetch
做同样的事情——因为它实际上运行的是 git fetch
——然后和 git merge
或 git rebase
做同样的事情,因为它实际上运行的是 7x1045 或 67
(您通常应该手动执行这两个步骤,至少在您足够了解 Git 之前,当任何一个步骤失败时,它们最终都会失败,您会认识到哪里出了问题并知道如何处理它。)
上游影响git merge
这实际上可能是最重要的。一旦你有一个上游集,git rebase
可以报告你当前分支与其上游之间的差异,就提交而言。
如果像正常情况一样,您在分支 git status
上,其上游设置为 git status
,并且您运行 B
,您将立即看到您是否有可以推送的提交,和/或可以 merge 或 rebase 的提交。
这是因为 origin/B
运行:
git status
:您在 git status
上有多少不在 git rev-list --count @{u}..HEAD
上的提交? B
:您在 origin/B
上有多少不在 git rev-list --count HEAD..@{u}
上的提交? 设置上游为您提供了所有这些东西。
为什么
origin/B
已经有一个上游集?当您第一次从某个远程克隆时,使用:
$ git clone git://some.host/path/to/repo.git
或类似的,Git 所做的最后一步基本上是
B
。这会检查您的本地分支 master
- 只有您没有本地分支 git checkout master
。另一方面,您确实有一个名为
master
的远程跟踪分支,因为您刚刚克隆了它。Git 猜测您的意思一定是:“让我创建一个新的本地
master
,它指向与远程跟踪 origin/master
相同的提交,并且,当您使用它时,将 master
的上游设置为 origin/master
。”对于您还没有的每个分支
master
都会发生这种情况。 Git 创建分支并使其“跟踪”(作为上游)相应的远程跟踪分支。但这不适用于新分支,即还没有远程跟踪分支的分支。
如果您创建一个新分支:
$ git checkout -b solaris
到目前为止,还没有
origin/master
。您的本地 git checkout
无法跟踪远程跟踪分支 origin/solaris
,因为它不存在。当您第一次推送新分支时:
$ git push origin solaris
在
solaris
上创建 origin/solaris
,因此也在您自己的 Git 存储库中创建 solaris
。但为时已晚:您已经拥有一个没有上游的本地 origin
。3现在,Git 不应该自动将其设置为上游吗?
大概。请参阅“实现不佳”和脚注 1。现在很难改变:有数百万个脚本使用 Git,其中一些很可能取决于其当前的行为。改变行为需要一个新的主要版本,nag-ware 强制你设置一些配置字段,等等。简而言之,Git 是其自身成功的受害者:今天,无论它有什么错误,只有在更改几乎不可见、明显好得多或随着时间的推移缓慢完成时,才能修复。
事实是,今天不会,除非您在
origin/solaris
期间使用 solaris
或 --set-upstream
。这就是消息告诉你的。你不必那样做。好吧,正如我们上面提到的,您根本不必这样做,但假设您想要一个上游。您已经通过较早的推送在
-u
上创建了分支 git push
,正如您的 solaris
输出所示,您的本地存储库中已经有了 origin
。您只是没有将其设置为
git branch
的上游。要立即设置,而不是在第一次推送期间,请使用
origin/solaris
。 solaris
子命令采用任何现有分支的名称,例如 git branch --set-upstream-to
,并将当前分支的上游设置为另一个分支。就是这样 - 这就是它所做的 - 但它具有上述所有含义。这意味着您可以只运行
--set-upstream-to
,然后环顾四周,然后根据需要运行 origin/solaris
或 git fetch
,然后进行新的提交并运行 git merge
,而无需额外的大惊小怪。1公平地说,当时并不清楚最初的实现是否容易出错。只有当每个新用户每次都犯同样的错误时,这一点才变得清晰。现在是“不那么差”,也不是说“很棒”。
2“从不”有点强,但我发现当我把这些步骤分开时,Git 新手会更好地理解事情,尤其是当我可以向他们展示
git rebase
实际做了什么,然后他们可以看到 git push
或 git fetch
下一步会做什么.3如果您将第一个
git merge
作为 git rebase
运行——即,如果添加 git push
标志——如果(且仅当)推送成功,Git 会将 git push -u origin solaris
设置为当前分支的上游。所以你应该在第一次推送时提供 -u
。实际上,您可以在以后的任何推送中提供它,并且它会在那时设置或更改上游。但我认为 origin/solaris
更容易,如果你忘记了。4 无论如何,通过 Austin Powers/Dr Evil 简单地说“one MILLLL-YUN”的方法来衡量。
关于git - 为什么我必须 "git push --set-upstream origin <branch>"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37770467/