"u"到底有什么作用?"git push -u origin master"和"git push origin master"有什么区别?

456

尽管我已经尽力理解,但显然我很菜,不擅长使用git。

来自kernel.org关于git push:

-u

--set-upstream

对于每个已经更新或成功上传的分支,添加上游(跟踪)引用,供无参数的 git-pull(1) 和其他命令使用。有关详细信息,请参见 git-config(1) 中的 branch.<name>.merge

这是来自git configbranch.<name>.merge:

branch.<name>.merge

branch.<name>.remote一起定义了给定分支的上游分支。它告诉git fetch/git pull合并哪个分支,还可以影响git push(参见push.default)。当在分支<name>中时,它告诉git fetch要标记为将在FETCH_HEAD中合并的默认refspec。该值的处理方式类似于refspec的远程部分,并且必须匹配从由"branch.<name>.remote" 给出的远程获取的ref。合并信息由git pull(首先调用git fetch)用于查找要合并的默认分支。如果没有此选项,则git pull默认合并第一个获取的refspec。指定多个值以获得章鱼合并。如果您希望设置git pull,使其从本地存储库的另一个分支合并到<name>中,则可以将branch.<name>.merge指向所需的分支,并使用特殊设置.(句号)作为branch.<name>.remote

我已经成功设置了一个与Github远程仓库连接的仓库,并且我已经成功用如下命令提交了第一个commit:

git push -u origin master

然后,我不知不觉中成功地将我的第二次提交推送到了远程仓库,使用的命令是:

git commit -m '[...]'

然而,由于错误的认为我需要再次从master推送到origin,我运行了以下命令:

# note: no -u
git push origin master

那个命令做了什么?好像完全没有任何效果。我是不是“撤销”了git push -u origin master命令?


91
尽管我尽力理解git,但显然我很糟糕。- 我从未有过像你这样成功地再造我的人。 - dgo
2
可以说git在某种程度上违反了任何(基于模式的)统一理解,仅仅因为它的用户界面没有以任何连贯的方式“设计”。因此,在很多情况下,你只能通过死记硬背来“知道”它,而不能进行推断。在这里,我正在SO上检查一些应该很明显的事情,而我从0.x版本开始就一直在使用git。 - ocodo
3个回答

432

关键是 "无参git-pull"。当你从分支执行git pull,不指定源远程或分支时,Git会查看branch.<名称>.merge设置以知道从哪里拉取。 git push -u为你正在推送的分支设置这些信息。

为了看到区别,让我们使用一个新的空分支:

$ git checkout -b test

首先,我们不使用 -u 进行推送:

$ git push origin test
$ git pull
You asked me to pull without telling me which branch you
want to merge with, and 'branch.test.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:

    [branch "test"]
    remote = <nickname>
    merge = <remote-ref>

    [remote "<nickname>"]
    url = <url>
    fetch = <refspec>

See git-config(1) for details.

现在如果我们添加 -u

$ git push -u origin test
Branch test set up to track remote branch test from origin.
Everything up-to-date
$ git pull
Already up-to-date.
请注意已设置跟踪信息,以便git pull在不指定远程或分支的情况下按预期工作。
更新:额外提示: - 如Mark在评论中提到的那样,除了git pull之外,这个设置还影响git push的默认行为。如果您习惯使用-u来捕获您打算跟踪的远程分支,则建议将您的push.default配置值设置为upstream。 - git push -u <remote> HEAD将当前分支推送到<remote>上同名的分支(并设置跟踪,这样之后可以使用git push)。

12
git push <remote> <branch>命令能使事情更加清晰明了。如果省略了<remote>或<branch>,Git会使用分支配置设置来回退,这些设置可以通过git push -u为您设置。 - dahlbyk
4
我已经将您标记为答案,但是您的评论有些让我感到困惑。在您的回答中,您展示了git push origin test(没有-u)后git确实会混淆。然后您展示了git push -u origin test可以消除这种歧义。这是笔误还是我又变傻了? - ClosureCowboy
2
我觉得我们之间存在误解。 :) 当我说git push <remote> <branch>是明确无歧义的时候,我的意思是相对于依赖于分支配置的git push而言。同样地,git pull <remote> <branch>也是明确无误的,而git pull则依赖于分支配置。一旦你使用了-u进行推送,git pushgit pull都将按预期工作。 - dahlbyk
12
你的答案没问题,但是在你之前的评论中,你重复了一个普遍存在的误解关于git push - 除非你自己设置了push.default,否则git push只使用上游分支配置来决定要推送到哪个远程,而不是更新远程分支。 - Mark Longair
2
Git 的最佳实践是 git push origin master,对于其他分支也是一样的,例如 git pull origin master。因此,如果分支发生变化,则可以使用 git push origin branch_namegit pull origin branch_name 来同步到另一侧。 - Arpit Vaishnav
显示剩余6条评论

119
git push -u origin master

...与以下代码等价:

git push origin master ; git branch --set-upstream master origin/master

如果你忘记了-u,那就执行最后一个语句!

或者你可以强制执行它:

git config branch.master.remote origin
git config branch.master.merge refs/heads/master

如果您让命令为您执行,它会像检查您是否输入了不存在的分支或者您没有git remote add一样,帮您捕捉错误,尽管这可能是您想要的结果。 :)


2
顺便提一下,master 只是一个例子 :) - sabgenton
好的,现在较新版本中第二个位已经被弃用,应使用以下命令:git branch master -u origin/master 详见 https://dev59.com/mnRB5IYBdhLWcg3wxZ1K#2286030。 - sabgenton
3
如果你忘记使用 -u 选项,输入 git push -u 即可。 - zeekvfu
2
较新版本的git表明--setup-upstream将被弃用:--set-upstream标志已被弃用并将被移除。请考虑使用--track--set-upstream-to - Bill Hoag
1
“--set-upstream”已被弃用,现在应使用以下命令:git branch --set-upstream-to=origin/master master - Alberto Perez
显示剩余2条评论

91
更简单的说,-u 标志在你推送到上游服务器时添加了一个跟踪引用。这里重要的是,它允许你不提供任何参数进行 git pull 操作。例如,一旦你执行了 git push -u origin master,以后就可以调用 git pull 命令,并且 Git 知道你实际想要执行的是 git pull origin master 命令,否则你将必须输入整个命令。

3
如果我将-u标志设置为origin master,那么每次拉取操作都将与该设置相关。如果我想更改git pull的行为,我应该运行git push -u origin some_other_branch,然后git pull就会引用some_other_branch了?谢谢! - Toma Tomov
3
我们是否也可以使用"git push"代替使用"git push origin master"? - cegprakash
2
是的,@cegprakash,你可以这样做。但是,你最初应该执行了 git push -u origin master - Adépòjù Olúwáségun
9
我想要一个简单的答案.. 我觉得这是最好的答案!!! 其他的听起来对我来说太技术化了,无法理解。 - Mac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接