为什么我需要一直做'--set-上游'?

我在Git中创建了一个新分支:

git branch my_branch

推它:

git push origin my_branch

现在假设有人在服务器上做了一些更改,我想从origin/my_branch中提取。我做:

git pull

但我得到:

You asked me to pull without telling me which branch youwant to merge with, and 'branch.my_branch.merge' inyour configuration file does not tell me, either. Pleasespecify which branch you want to use on the command line andtry again (e.g. 'git pull <repository> <refspec>').See git-pull(1) for details.
If you often merge with the same branch, you may want touse something like the following in your configuration file:
[branch "my_branch"]remote = <nickname>merge = <remote-ref>
[remote "<nickname>"]url = <url>fetch = <refspec>
See git-config(1) for details.

我知道我可以让它工作:

git branch --set-upstream my_branch origin/my_branch

但是为什么我需要对我创建的每个分支执行此操作?如果我将my_branch推入origin/my_branch,那么我想将origin/my_branch拉入my_branch,这不是很明显吗?我如何使这成为默认行为?

1231681 次浏览

一个不依赖于记住git branch --set-upstream1语法的快捷方式是:

git push -u origin my_branch

…第一次推送该分支。或者,从同名分支推送到当前分支(对于别名很方便):

git push -u origin HEAD

您只需要使用-u一次,这就像git branch --set-upstream一样建立了您的分支与origin之间的关联。

就我个人而言,我认为必须明确地设置你的分支和远程分支之间的关联是一件好事。


1这可能听起来很愚蠢,但我经常忘记指定当前分支,假设这是默认的-它不是,结果是最令人困惑的。

更新2012-10-11:显然我不是唯一一个发现容易出错的人!感谢VonC指出git 1.8.0引入了更明显的git branch --set-upstream-to,如果您在分支my_branch上,可以使用如下:

git branch --set-upstream-to origin/my_branch

…或者短选项:

git branch -u origin/my_branch

这种变化及其推理在git 1.8.0的发行说明,发布版本1中进行了描述:

git branch --set-upstream origin/master很诱人,但这会告诉Git安排本地分支origin/master与当前签出的分支集成,这不太可能是用户的意思。该选项已弃用;使用新的--set-upstream-to(带有简短的-u)选项。

Git v2.37.1及以上

如果您使用的是上述版本或更高版本,您可以使用此新配置条目自动设置远程跟踪:

git config --global push.autoSetupRemote true

你可以简单地

git checkout -b my-branch origin/whatever

如果您将branch.autosetupmergebranch.autosetuprebase(我最喜欢的)设置为always(默认为true),my-branch将自动跟踪origin/whatever

git help config

您还可以显式地告诉git拉取要拉取的远程分支(正如它在错误消息中提到的那样):

git pull <remote-name> <remote-branch>

但要小心这一点:如果您在不同的分支上并执行显式拉取,您拉取的refspec将合并到您所在的分支中!

值得一提的是,如果您正在尝试跟踪远程上已经存在的分支(例如起源/某个分支),但还没有在本地签出它,您可以这样做:

$ git checkout --track origin/somebranch

注意:'-t'是'--Track'选项的缩短版本。

这会立即建立相同的关联。

你可以用更少的键入来实现这一点。首先,改变推送的工作方式:

git config --global push.default current

这将推断origin my_branch部分,因此您可以执行:

git push -u

这将创建具有相同名称的远程分支并跟踪它。

您可以通过两种方式简化上游设置。首先,当您创建分支时:

git branch -u origin/my-branch

或者创建分支后,您可以使用此命令。

git push -u origin my-branch

您还可以在单个命令中分支、签出和设置上游:

git checkout -b my-branch -t origin/my-branch

我个人的偏好是在两步命令中执行此操作:

git checkout -b my-branchgit push -u origin my-branch

您可以使用:

git config --global branch.autosetupmerge always

它将在您每次创建或签出新分支时链接上游分支。

https://felipec.wordpress.com/2013/09/01/advanced-git-concepts-the-upstream-tracking-branch/

这也适用于branch.autosetuprebase,如果您遵循更注重rebase的工作流程,但除非您知道自己在做什么,否则不要使用它,因为它将默认您的拉取行为为rebase,这可能会导致奇怪的结果。

git branch --set-upstream-to=origin/master<branch_name>

更新时间:push.autoSetupRemote现在终于以更简单的方式解决了这个问题!有关更多信息,请参阅另一个答案在这里

原答复:

我使用这个Git别名,而不是每次从Git复制/粘贴建议:https://gist.github.com/ekilah/88a880c84a50b73bd306

源代码复制如下(将其添加到您的~/.gitconfig文件中):

[alias]pushup = "!gitbranchname() { git symbolic-ref --short HEAD; }; gitpushupstream() { git push --set-upstream origin `gitbranchname`; }; gitpushupstream"

顺便说一下,将当前分支推送到同名远程的快捷方式:

$ git push -u origin HEAD

因为git有很酷的能力,可以将不同的分支推/拉到不同的“上游”存储库。你甚至可以在同一个分支上使用单独的存储库进行推和拉。这可以创建一个分布式的、多级的流程,我可以看到这在Linux内核等项目上很有用。Git最初是为了在那个项目上使用而构建的。

因此,它不会假设您的分支应该跟踪哪个存储库。

另一方面,大多数人不会以这种方式使用git,所以它可能是默认选项的一个很好的例子。

Git通常是非常低级的,它可能会令人沮丧。然而,有GUI,如果您仍然想从shell使用它,编写帮助脚本应该很容易。

您可以设置一个非常好的别名,可以在没有过于冗长的语法的情况下处理此问题。

我在~/.gitconfig中有以下别名:

po = "!git push -u origin \"$(git rev-parse --abbrev-ref HEAD)\""

在新分支上提交后,您可以通过简单地键入命令来推送您的新分支:

git po

你也可以做git push -u origin $(current_branch)

由于这个问题(仅限OS X),我有点重新发现了#0。现在我在分支时使用的只是这两个命令:

legit publish [<branch>]将指定的分支发布到远程。(别名:pub

legit unpublish <branch>从远程删除指定的分支。(别名:unp

SublimeGit默认支持legit,这使得整个分支例程像按Ctrl-b一样简单。

这是我最常用的该死的

$ git pushfatal: The current branch master has no upstream branch.To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
$ fuckgit push --set-upstream origin master [enter/↑/↓/ctrl+c]Counting objects: 9, done....

此外,在终端中键入脏话也很有趣。

我们使用phabricator,不使用git推送。我必须创建适用于Linux的bash别名 /mac

vim ~/.bash_aliases
new_branch() {git checkout -b "$1"git branch --set-upstream-to=origin/master "$1"}

保存

source ~/.bash_aliasesnew_branch test #instead of git checkout -b testgit pull

对于那些寻找与git pull一起使用的别名的人,这是我使用的:

alias up="git branch | awk '/^\\* / { print \$2 }' | xargs -I {} git branch --set-upstream-to=origin/{} {}"

每当你得到:

$ git pullThere is no tracking information for the current branch....

只需运行:

$ upBranch my_branch set up to track remote branch my_branch from origin.$ git pull

你可以走了

我个人在bash中使用以下别名

在~/. gitconfig文件

[alias]pushup = "!git push --set-upstream origin $(git symbolic-ref --short HEAD)"

并在~/. bashrc或~/. zshrc文件中

alias gpo="git pushup"alias gpof="gpo -f"alias gf="git fetch"alias gp="git pull"

这是git推送的bash别名,每次推送都可以安全运行,并且会自动在第一次推送的上游设置和之后进行正常推送之间切换。

alias gpu='[[ -z $(git config "branch.$(git symbolic-ref --short HEAD).merge") ]] && git push -u origin $(git symbolic-ref --short HEAD) || git push'

原文

如果下面的方法不起作用:

git config --global push.default current

您还应该更新项目的本地配置,因为您的项目可能具有本地git配置:

git config --local push.default current

我想要的只是做这样的事情:

git checkout -b my-branchgit commit -a -m "my commit"git push

由于我没有找到更好的解决方案,我刚刚在~/.bashrc上创建了一个bash别名:

alias push="git push -u origin HEAD"

现在只需执行push命令即可完成工作(您也可以在~/.gitconfig上添加此别名并使用其他名称,例如pushup

99%的时间我想将上游设置为同名的分支,所以我使用这个(在*nix或Git Bash中):

git branch --set-upstream-to=origin/$(git branch --show-current)

这很好,因为它与分支无关。注意子命令git branch --show-current打印您当前的分支名称,如果您是分离的,则不打印任何内容。

附带说明:我有我的配置集,这样我就可以使用git push -u,所以我很少需要这样做。但我有时仍然会这样做,通常是当我决定要将本地更改重置为远程上的任何更改时,在那一刻,我意识到我之前没有使用-u。所以,通常我在设置上游后要运行的下一个命令是重置到远程分支:

git reset --hard @{u}

这也恰好与分支无关。(也许我真的不喜欢输入我的分支名称。)

显然没有支持的方法来覆盖git命令的默认选项。基于这个答案定义同名的git别名以阴影原始命令,我们可以覆盖bash中git push的行为以始终调用git push -u。将以下内容放入您的~/.bash_profile文件中,它应该等效于每次推送时运行--set-上游。

function do_git {cmd=$1shiftmyArgs=( "$@" )
if [ "$cmd" == "push" ]; thenmyArgs=( "-u" "${myArgs[@]}" )fimyArgs=( "$cmd" "${myArgs[@]}" )
$(which git) "${myArgs[@]}"}alias  git='do_git'

我做了一些类似于许多其他用户的事情,但想分享它作为替代方案,因为我没有看到其他人发布这个。

alias gpu='git push --set-upstream origin $(git branch --show-current)'

(oh-my-zsh已经有一个gpu别名,所以在. oh-my-zsh/plugins/git/git.plugin.zsh中进行了编辑)

这里有很多很好的答案,但是,所有这些都要求您在运行git pull之前正确执行其他操作

使用别名来做诸如“通过创建本地正确跟踪的远程分支,使git推送以应有的方式工作”之类的事情当然会有所帮助。然而,当您忘记使用它们或经历了不同的工作流程时,这些都没有帮助。

这是一个bash函数,您可以使用它来执行拉取它应该工作的方式,通过检测何时没有配置远程合并目标,但远程上有一个与本地分支同名的分支,并将该分支设置为合并目标,然后拉取。

git-pulldown() {head="$(git rev-parse --abbrev-ref HEAD)"
if [[ $(git config "branch.$head.merge") ]]; then #there's already a merge target configured, just pull as normal from theregit pullelseif [[ $(git ls-remote --heads origin $head) ]]; then #there is an upstream branch existing with the same name as our branchgit branch --set-upstream-to origin/$head #set merge target to upstream branch with same namegit pullelse #fail with explanationecho "Branch $head has no upstream or merge target! You will likely have to push first, or manually configure it"return 1fifi}

oh-my-zsh的git插件已经将其别名为gpsup。这会将上游推送并设置到分支。一气呵成!

我个人挖掘标准化和一致的解决方案。会推荐其他人使用相同的别名。:)

git config --global push.autoSetupRemote true

OP问:

我知道我可以让它工作:

git branch --set-upstream my_branch origin/my_branch

但是为什么我需要为我创建的每个分支执行此操作?

您不需要一直设置上游。
11年后的今天

在Git 2.37(2022年第三季度)中,#0将为您解决这个问题。

提交05d5775提交8a649be提交bdaf1df(2022年4月29日)by陶克勒克斯(#0)
(由提交f49c478中的Junio C Hamano----#0----合并,2022年5月26日)

#0:新的配置选项“push.autoSetupRemote”支持“simple”推送

署名:陶克勒克斯

在一些“simple”集中式工作流程中,用户希望远程跟踪分支名称与本地分支名称匹配。
#0man)推送到分支的远程版本/实例,“#1man)拉取对远程分支的任何更改(同一用户在另一个地方或其他用户所做的更改)。

push.default默认选项“simple”支持这种期望,它拒绝对不匹配的跟踪分支名称进行默认推送,新的branch.autosetupmerge选项“simple”仅为同名远程分支设置远程跟踪。

当用户创建了一个新分支并且尚未推送(并且push.default未设置为“current”)时,会提示用户“The current branch %s has no upstream branch”错误,以及有关如何推送和添加跟踪的说明。

这个错误很有帮助,因为按照每个分支一次的建议永远“解决”该分支的问题,但不方便的是,对于“简单”的集中式工作流,这总是正确的做法,所以最好只是这样做。

使用新的配置设置push.autoSetupRemote支持此工作流,这将导致默认推送,当没有配置远程跟踪分支时,推送到远程和--set-upstream上的同名。

还添加一个提示,当遇到“The current branch %s has no upstream branch”错误时提供此新选项,并添加相应的测试。

新的提示是:

要自动对没有跟踪的分支执行此操作
上游,请参阅“git help config”中的“push.autoSetupRemote

git config现在包含在其手册页中:

push.autoSetupRemote

如果设置为“true”,则在默认推送时假设--set-upstream当前分支存在上游跟踪;

此选项与push.default选项“simple”、“upstream”和“current”一起生效。

如果默认情况下您希望将新分支推送到默认远程(如'push.default=current'的行为)并且您还希望设置上游跟踪,那么它很有用。
最有可能受益于此选项的工作流是“simple”中央工作流,其中所有分支都应在远程具有相同的名称。

在git2.37.0或更高版本中,您可以告诉git自动设置远程。这是通过

git config --global --add --bool push.autoSetupRemote true

然后你可以只写git push,它会推送到默认的远程。