关于git:为什么我一直需要做`–set-upstream`?

Why do I need to do `--set-upstream` all the time?

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

1
git branch my_branch

推动它:

1
git push origin my_branch

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

1
git pull

但我得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
You asked me to pull without telling me which branch you
want to merge with, and 'branch.my_branch.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"my_branch"]
    remote = <nickname>
    merge = <remote-ref>

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

See git-config(1) for details.

我了解到,我可以让它与:

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

但是为什么我要为我创建的每个分支都这样做呢?如果我把my_branch推到origin/my_branch中,那么我会把origin/my_branch拉到my_branch中,这不是很明显吗?我如何才能将此设置为默认行为?


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

1
git push -u origin my_branch

…你第一次推那根树枝。或者,将当前分支推送到同名分支(别名很方便):

1
git push -u origin HEAD

你只需要使用一次-u,这就建立了你的分支机构和origin的分支机构之间的联系,就像git branch --set-upstream一样。

就个人而言,我认为在您的分支和远程分支之间明确地建立这种关联是一件好事。对于git pushgit pull来说,这些规则不同只是一个遗憾。

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

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

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

…或选择卖空:

1
git branch -u origin/my_branch

Git 1.8.0的发行说明(候选版本1:

It was tempting to say git branch --set-upstream origin/master, but that tells Git to arrange the local branch origin/master to integrate with the currently checked out branch, which is highly unlikely what the user meant. The option is deprecated; use the new --set-upstream-to (with a short-and-sweet -u) option instead.


你可以少打字就可以做到这一点。首先,改变你的推送方式:

1
git config --global push.default current

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

1
git push -u

这两者都将创建具有相同名称的远程分支并对其进行跟踪。


你可以简单地

1
git checkout -b my-branch origin/whatever

首先。如果您将branch.autosetupmergebranch.autosetuprebase设置为always(默认为truemy-branch将自动跟踪origin/whatever

git help config


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

1
git branch -u origin/my-branch

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

1
git push -u origin my-branch

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

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

我个人的偏好是通过两步命令来完成:

1
2
git checkout -b my-branch
git push -u origin my-branch


这是我最常用的。

1
2
3
4
5
6
7
8
9
10
$ git push
fatal: 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

$ fuck
git push --set-upstream origin master [enter/↑/↓/ctrl+c]
Counting objects: 9, done.
...

另外,在你的终端里输入脏话也很有趣。


您可以使用:

git config --global branch.autosetupmerge always

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

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

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


顺便说一下,将当前分支推送到具有相同名称的远程服务器的快捷方式:

1
$ git push -u origin HEAD


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


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

在~/.gitconfig文件中

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

在~/.basehrc或~/.zshrc文件中

1
2
3
4
alias gpo="git pushup"
alias gpof="gpo -f"
alias gf="git fetch"
alias gp="git pull"


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

埃多克斯1〔15〕

但是,要小心:如果您在一个不同的分支上并执行显式拉操作,那么您拉的refspec将合并到您所在的分支中!


值得一提的是,如果您试图跟踪远程上已经存在的分支(如origin/somebranch),但尚未在本地签出该分支,则可以执行以下操作:

1
$ git checkout --track origin/somebranch

注意:"-t"是"--track"选项的缩短版本。

这会立刻建立起相同的联系。


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

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

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


您可以设置一个非常好的别名来处理这个问题,而不必使用过于冗长的语法。

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

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

在对新分支进行提交之后,只需键入以下命令即可推送新分支:

1
git po


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

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

现在只要你得到:

1
2
3
$ git pull
There is no tracking information for the current branch.
...

只需运行:

1
2
3
$ up
Branch my_branch set up to track remote branch my_branch from origin.
$ git pull

你可以走了


你也可以做EDOCX1[1]


因为Git有很酷的能力将不同的分支推/拉到不同的"上游"存储库。甚至可以使用不同的存储库来推拉同一个分支。这可以创建一个分布式的、多层次的流,我可以看到这在Linux内核等项目中非常有用。Git最初是为在那个项目上使用而建造的。

因此,它不会假设分行应该跟踪哪个回购。

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

Git通常是相当低的级别,这可能会令人沮丧。然而,还有一些GUI,如果您仍然想从shell中使用它,那么编写助手脚本应该很容易。


如果以下内容不起作用:

1
git config --global push.default current

您还应该更新项目的本地配置:

1
git config --local push.default current

您的项目可能有本地Git配置。然后一个简单的

1
git push

应该在不需要一直设置上游的情况下工作。


因为这个问题,我重新发现了legit(仅限OS X)。现在,当分支时,我只使用这两个命令:

埃多克斯1〔3〕将指定的分支发布到远程。(别名:pub)

埃多克斯1〔5〕从远程删除指定的分支。(别名:unp)

Sublimegit默认带有legit支持,这使得整个分支例程和按ctrl-b一样容易。


我们使用phabricator,不使用git。我必须创建在Linux/Mac上工作的bash别名

1
2
3
4
5
6
vim ~/.bash_aliases

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

节约

1
2
3
source ~/.bash_aliases
new_branch test #instead of git checkout -b test
git pull


这里有一个git push的bash别名,它可以安全地运行于每次推送中,并自动在第一次推送的设置上游和之后的正常推送之间切换。

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

原岗位