我创建了一个本地分支来测试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上看到了这个问题和答案:我猜这是另一个不完整或错误的接受答案的例子。或者,这是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
8条答案
按热度按时间zyfwsgd61#
TL;DR:
git branch --set-upstream-to origin/solaris
您提出的问题的答案-我将其重新措辞为“我必须设置上游吗”-是:不,你根本不需要设置upstream。
但是,如果当前分支没有upstream,Git会改变它在
git push
和其他命令上的行为。这里完整的推送故事很长很无聊,可以追溯到Git版本1.5之前。1从Git 2.0版本开始,Git现在有一个配置旋钮拼写为
push.default
,现在默认为simple
。在Git 2.0之前和之后的几个版本中,每次运行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
,则设置upstream对git push
没有任何作用。(All假设你的Git版本至少是2.0。
上行影响
git fetch
如果你不带额外的参数运行
git fetch
,Git会通过查询当前分支的上游来计算从哪个远程获取。如果上游是一个远程跟踪分支,Git会从该远程分支获取。(如果上游分支没有设置或者是本地分支,Git会尝试获取origin
。)上行也影响
git merge
和git rebase
如果你不带任何附加参数运行
git merge
或git rebase
,Git会使用当前分支的upstream。因此它缩短了这两个命令的使用。上行影响
git pull
无论如何都不应该2使用
git pull
,但是如果使用了,git pull
会使用upstream设置来确定从哪个remote获取,然后使用哪个分支进行合并或变基。也就是说,git pull
与git fetch
做同样的事情-因为它实际上运行 *git fetch
-然后与git merge
或git rebase
做同样的事情,因为它实际上运行 *git merge
或git rebase
。(You我通常应该手动完成这两个步骤,至少直到你足够了解Git,当任何一个步骤失败时,他们最终会,你认识到哪里出错了,知道该怎么做。
上行影响
git status
这实际上可能是最重要的。一旦你有了一个上游集合,
git status
就可以报告你的当前分支和它的上游分支之间的提交差异。如果像正常情况一样,你在分支 *
B
* 上,其上游设置为origin/*B*
,并且你运行git status
,你会立即看到你是否有可以推送的提交,和/或可以合并或变基的提交。这是因为
git status
运行:git rev-list --count @{u}..HEAD
:你有多少提交在 *B
* 上,而不是在origin/*B*
上?git rev-list --count HEAD..@{u}
:你在origin/*B*
上有多少提交不在 *B
* 上?设置一个upstream会给你所有这些东西。
为什么
master
已经有上行集了?首次从某个远程克隆时,使用:
或者类似的,Git执行的最后一步实际上是
git checkout master
。这将检查您的本地分支master
-只是您没有本地分支master
。另一方面,您确实有一个名为
origin/master
的远程跟踪分支,因为您刚刚克隆了它。Git猜测你的意思一定是:“为我创建一个新的本地
master
,它指向与远程跟踪origin/master
相同的提交,同时将master
的上游设置为origin/master
。”这会发生在你
git checkout
还没有的 * 每个 * 分支上。Git创建分支 * 并 * 使其“跟踪”(作为上游)相应的远程跟踪分支。但这不适用于 new 分支,即尚未 * 远程跟踪分支的分支。
如果创建一个 new 分支:
到目前为止,还没有
origin/solaris
。您的本地solaris
* 无法 * 跟踪远程跟踪分支origin/solaris
,因为它不存在。第一次推送新分支时:
在
origin
上 * 创建 *solaris
,因此也在您自己的Git存储库中创建origin/solaris
。但为时已晚:您已经有一个本地solaris
,* 没有上游 *。3现在Git不应该自动设置为上游吗?
可能吧,见“执行不力”和脚注1。现在很难改变:有数以百万计的脚本使用Git,其中一些可能依赖于它的当前行为。更改行为需要一个新的主要版本,nag-ware强制您设置一些配置字段,等等。简而言之,Git是其自身成功的受害者:今天,无论它有什么错误,只有当改变要么是无形的,要么是明显的好得多,要么是随着时间的推移慢慢完成的时候,才能被修复。
事实上,它今天没有,* 除非 * 你在
git push
期间使用--set-upstream
或-u
。这就是信息告诉你的。你不必这样做。好吧,正如我们上面提到的,你根本不必这样做,但让我们假设你想要一个上游。您已经在
origin
上创建了分支solaris
,通过之前的推送,正如您的git branch
输出所示,您已经在本地存储库中 * 拥有 *origin/solaris
。只是没有将其设置为
solaris
的上游。要立即设置它,而不是在第一次推送时设置,请使用
git branch --set-upstream-to
。--set-upstream-to
子命令采用任何现有分支的名称,例如origin/solaris
,并将当前分支的上游设置为另一个分支。这就是它所做的一切,但它具有上面提到的所有含义。这意味着你可以只运行
git fetch
,然后四处看看,然后运行git merge
或git rebase
,然后进行新的提交并运行git push
,而无需一堆额外的麻烦。1公平地说,当时并不清楚最初的实现是否容易出错。只有当每个新用户每次都犯同样的错误时,这一点才变得清晰起来。现在是“不那么穷了”,这并不是说“很棒”。
2“Never”这个词有点过了,但是我发现当我把步骤分开时,Git新手会更好地理解事情,特别是当我可以向他们展示
git fetch
实际做了什么,然后他们可以看到git merge
或git rebase
下一步会做什么。3如果你将 first
git push
作为git push -u origin solaris
运行--也就是说,如果你添加了-u
标志--当(且仅当)推送成功时,Git会将origin/solaris
设置为当前分支的上游。所以你应该在 * 第一次 * 推送时提供-u
。事实上,你可以在以后的任何推送中提供它,它会在那个时候设置 * 或更改 * 上游。但我认为git branch --set-upstream-to
更容易,如果你忘记了。无论如何,用奥斯汀·鲍尔斯/邪恶博士简单地说“一个百万云”的方法来衡量。
cnjp1d6j2#
之间的区别
和
它们都可以很好地推送到远程存储库,但是当您拉取时,您会注意到差异。
如果您这样做:
拉的时候,你要做到:
但如果您这样做:
那么在拉的时候,你只需要做:
因此,添加
--set-upstream
允许不必指定每次执行git pull
时要从哪个分支中提取。zsbz8rwp3#
你可以配置git来自动执行这个操作:
git config --global push.default current
这是你在99%的情况下想要的,无论如何,在我的经验。
j91ykkif4#
一个基本完整的命令就像
git push <remote> <local_ref>:<remote_ref>
。如果你只运行git push
,git不知道该怎么做,除非你做了一些配置来帮助git做出决定。在git repo中,我们可以设置多个remote。我们还可以将本地引用推送到任何远程引用。完整命令是执行push的最直接的方法。如果你想输入更少的单词,你必须先配置,比如--set-upstream。ws51t4hk5#
在Git 2.37.0版本中,不需要使用--set-upstream origin。你可以在启用push.autoSetupRemote后直接使用git push,方法如下:
来源:James Ide's tweet
希望这有帮助!
jdzmm42g6#
-u
标志指定您要将本地分支链接到上游分支。这也将创建一个上游分支(如果不存在)。这些答案都没有涵盖我是如何做到这一点的(完整的形式),所以在这里:所以如果你的本地分支名字是咖啡
oxiaedzo7#
我的理解是,
-u
或--set-upstream
允许您为您所在的分支指定上游(远程)存储库,因此下次运行git push
时,您甚至不必指定远程存储库。推流设置上游(远程)仓库为原点:
下次推送时,您不必指定远程存储库:
4si2a6ki8#
tl;dr如果你不想考虑这一点,也不想修改你的配置:
git push --set-upstream origin $(git branch --show-current)