ChatGPT解决这个技术问题 Extra ChatGPT

为什么我需要一直做`--set-upstream`?

我在 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 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.

我了解到我可以使用它:

git branch --set-upstream my_branch origin/my_branch

但是为什么我需要为我创建的每个分支都这样做呢?如果我将 my_branch 推入 origin/my_branch,那么我想将 origin/my_branch 拉入 my_branch,这不是很明显吗?我怎样才能使它成为默认行为?

branch.autosetupmerge 的默认值意味着新分支的上游配置仅在从远程跟踪分支(例如 <remote-name>/<branch-name>)创建分支时自动设置(参见 git-config(1))。您可能正在从现有的本地分支创建分支。如果您有效地直接从远程分支的尖端分支(尽管位于本地分支上),那么您可以使用 git branch my_branch <remote-name>/<branch-name> 自动设置上游配置。
仅供参考,--set-upstream 选项已弃用。您应该改用 --track--set-upstream-to
如果不推荐使用 --set-upstream,那么 git 开发人员可能应该将它从当您运行 git push 时显示的帮助消息中删除,而没有选项并且没有设置上游?
@ChristopherHunter 你的评论已经过去一年多了,它仍然这么说。这只是一个草率的反馈,还是有一个我们不知道的技术上明智的理由来保留它?
@ChristopherHunter git branch --set-upstream 已弃用。 git push --set-upstream 不是。

A
Andrew Swift

不依赖于记住 git branch --set-upstream 1 语法的快捷方式是:

git push -u origin my_branch

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

git push -u origin HEAD

您只需使用 -u 一次,就可以像 git branch --set-upstream 一样在您的分支和 origin 处的分支之间建立关联。

就个人而言,我认为必须在您的分支和远程分支之间明确建立关联是一件好事。规则是 different for git push and git pull 真是太可惜了。

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

此更改及其原因在 the release notes for git 1.8.0, release candidate 1 中进行了描述:

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


另请注意,即使您在第一次推送时忘记了 -u,您也可以使用该标志再次运行推送,它将开始跟踪。
这些都不满足使用不带参数的 git push 的用例。第一次将我的新分支移动到远程时,我仍然必须记住“git push -u origin my-branch”。
自我注意:对第一个 git push -u origin master 的更完整解释:stackoverflow.com/a/17096880/6309
我也讨厌记住那个语法,所以我创建了以下别名:alias gpo="git push --set-upstream origin $(git branch | awk '/^\* / { print $2 }')"
这一切都很好,但我仍然认为 OP 的投诉是有效的。您启动一个本地分支,对其进行处理,将其推送到源以共享(没有参数);为什么不应该设置上游?在将新分支推送到远程时,出于某种原因不设置上游实际上是可取的吗?
Z
Zamith

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

git config --global push.default current

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

git push -u

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


在新创建的存储库中为新创建的分支运行 git push -u 时,git 如何推断 origin?是否假设存储库已被克隆,因此当前分支的远程设置为 origin
这应该是默认值。如果 git 提供更好的默认值,那么 git 中的许多东西可能会更加用户友好。
请注意,'current' 比使用 'simple' 做同样的事情稍微不安全,请参阅 stackoverflow.com/questions/23918062/…
确实如此,但是当您尝试 pull 时,您必须指定从哪里开始。 -u 设置源站和本地存储库之间的分支跟踪。
虽然有点方便,但这个 still 要求对第一个也是唯一一个 push 运行不同的命令——这违背了这个问题的全部观点。简而言之,没有好的答案。 Git 开发人员在面对广泛的社区异议时坚持保留这种尴尬的用户体验 (AUX) 是……启发性的。并且令人沮丧。 (主要是令人沮丧的。)
T
Tamlyn

这是我最常使用的 The Fuck

$ 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.
...

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


T
Tobu

你可以简单地

git checkout -b my-branch origin/whatever

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

请参阅git help config


这会产生“致命:无法更新路径并同时切换到分支'my-branch'。”
顺便说一句,我通常只是 git checkout -t origin/whatever,它也选择 whatever 作为新的分支名称。很方便!
@cdunn 这个很理想,但几乎没有一致性。该标志应称为 -u/--set-upstream
尝试创建新分支时,git checkout -t origin/whatever 对我不起作用:fatal: Cannot update paths and switch to branch 'whatever' at the same time.
git checkout -b my-branch origin/whatever 也有同样的错误(我正在尝试创建一个本地或远程不存在的新分支):fatal: Cannot update paths and switch to branch 'whatever' at the same time.
T
Tzen

您可以通过两种方式更简单地设置上游。首先在创建分支时:

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-branch
git push -u origin my-branch

很好的答案!解决两个常见用例。运行 git branch -u origin/my-branch 后,我可以运行 git pull 来下拉我的更改。
“git checkout -b my-branch -t origin/my-branch” 如果 'origin/my-branch' 尚不存在,这将不起作用。
实际上,您可以在没有 -b my-branch 的情况下执行 git checkout -t origin/my-branch,它只会自动推断 my-branch 以获取本地分支名称。但是,正如@Spongman 提到的,如果 origin/my-branch 首先不存在,则此命令不起作用。
是的,会工作@wisbucky,-t 工作得很好。不过就个人而言,即使在我写完该回复两年后,我仍然更喜欢用 checkout -b 和 push -u 分成两行。当我没有遥控器时,它更明确,并且在 checkout -b 上没有错误 - 这在实验时经常发生:)
fatal: 'origin/my-branch' does not appear to be a git repository 对我来说 git push -u origin/my-branch 失败。这有效:git push -u origin my-branch
v
vy32

您可以使用:

git config --global branch.autosetupmerge always

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

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

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


不起作用,我仍然收到 --set-upstream 消息
@Dorian,您必须在创建分支之前设置它。请参阅stackoverflow.com/a/9753268/263998
我得到:致命:您当前分支的上游分支与您当前分支的名称不匹配...
但这不会将跟踪分支设置为具有相同分支的远程分支,而是设置为当前本地分支。所以当你推送它时,它会尝试推送到你在创建新分支之前的本地分支。
小心这个设置!!设置后,您将获得此行为。 1. 切换到 master。 2. 运行 git checkout -b new_branch。 3. 向该分支添加提交。 4. git push origin new_branch这会将提交推送到源上的 master 分支(而不是源上名为 new_branch 的新分支)。
d
djanowski

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

$ git push -u origin HEAD

y
youngrrrr

如果以下不起作用:

git config --global push.default current

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

git config --local push.default current

更多的解释会很棒。第一行是做什么的?
这个答案是合法的。所有提出别名的都是愚蠢的解决方法。其他证明记住长命令序列的理由是迂腐的。
这适用于推动而不是拉动。推送时它使用正确的上游,但不设置上游,因此您仍然需要运行命令来设置上游,然后才能第一次拉出分支。
@rspeer 不确定你的意思?这适用于拉取,但如果您还没有执行提取(或拉取也执行提取),则您无法签出自上次执行提取后远程创建的分支 - 已经并将始终如此。您可能会争辩说养成运行 git fetch --prune 的习惯是值得的,因此如果远程分支被远程删除,您也会在本地删除远程分支。
@JohnySkovdal 我的意思是:如果您运行此配置,创建一个分支并推送该分支,则无法将更新拉到您创建的同一分支,因为您没有设置它的上游。许多工作流程可以从自动设置上游的方式中受益,这就是问题所要求的。
J
Jeff Rosenberg

我个人在 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"

我只需要hcange .gitconfig,然后我可以使用命令git pushup,它总是将当前分支推送到原点。我总是可以只使用 git pushup 而不是 git push 👍
只是扩展此答案以设置全局 git 别名(自定义命令) - git config --global alias.pushup "!git push --set-upstream origin $(git symbolic-ref --short HEAD)"
V
VonC
git config --global push.autoSetupRemote true

OP问:

我了解到我可以使用它: git branch --set-upstream my_branch origin/my_branch 但是为什么我需要为我创建的每个分支都这样做呢?

您不需要一直设置上游。不再是(十一年后)。

在 Git 2.37(2022 年第三季度)中,git config --global push.autoSetupRemote true 将为您解决这些问题。

请参阅 Tao Klerks (TaoK)commit 05d5775commit 8a649becommit bdaf1df(2022 年 4 月 29 日)。
(由 Junio C Hamano -- gitster --commit f49c478 中合并,2022 年 5 月 26 日)

push:新配置选项“push.autoSetupRemote”支持“简单”推送签名者:Tao Klerks

在一些“简单”的集中式工作流程中,用户希望远程跟踪分支名称与本地分支名称匹配。 “git push”(man)推送到分支的远程版本/实例,“git pull”(man)将任何更改拉到远程分支(同一用户在另一个地方或其他用户所做的更改)。 push.default 默认选项“simple”支持这种期望,它拒绝默认推送不匹配的跟踪分支名称,以及新的 branch.autosetupmerge 选项“simple”,它只为同名远程设置远程跟踪分支机构。当用户创建了新分支但尚未推送(并且 push.default 未设置为“当前”)时,会提示用户“当前分支 %s 没有上游分支”错误,并且有关如何推送和添加跟踪的说明。这个错误有助于每个分支遵循一次建议永远“解决”该分支的问题,但对于“简单”集中式工作流程来说不方便,这始终是正确的做法,所以最好只做。使用新的配置设置 push.autoSetupRemote 支持此工作流程,这将导致默认推送,当没有配置远程跟踪分支时,推送到远程和 --set-upstream 上的同名。当遇到“当前分支 %s 没有上游分支”错误时,还添加一个提供此新选项的提示,并添加相应的测试。

新的提示是:

要让没有跟踪上游的分支自动发生这种情况,请参阅“git help config”中的“push.autoSetupRemote”

git config 现在在其 man page 中包含:

push.autoSetupRemote 如果设置为“true”,当当前分支不存在上游跟踪时,默认推送时假定 --set-upstream;此选项与 push.default 选项“simple”、“upstream”和“current”一起生效。如果默认情况下您希望将新分支推送到默认远程(如 'push.default=current' 的行为)并且您还希望设置上游跟踪,这很有用。最有可能从此选项中受益的工作流程是“简单”的中央工作流程,其中所有分支都应在远程具有相同的名称。


m
mattacular

对于它的价值,如果您尝试跟踪远程上已经存在的分支(例如 origin/somebranch)但尚未在本地检查它,您可以执行以下操作:

$ git checkout --track origin/somebranch

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

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


您实际上可以只结帐到分行。所以 git checkout somebranch 是等价的。
@Zamith这不是只有在事先立即调用 git fetch 后才有效吗?
不是立即,但是是的,您确实需要在本地存储库中引用该分支,每当您调用 git fetchgit pull 时都会发生这种情况。不过,我从来没有发现这是一个问题。
m
manroe

更新: push.autoSetupRemote 现在终于以更简单的方式解决了这个问题!有关详细信息,请参阅 other answer on that here

原答案:

我每次都使用这个 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"

m
mtbkrdave

您还可以明确告诉 git pull 要拉哪个远程分支(如错误消息中所述):

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

但是请注意这一点:如果您在不同的分支上并进行显式拉取,则您拉取的 refspec 将被合并到您所在的分支中!


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

不再支持。
1
123

您可以设置一个非常好的别名来处理此问题,而无需过于冗长的语法。

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

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

在新分支上提交后,您只需键入以下命令即可推送新分支:

git po

为什么是popush origin?如果多次运行会发生什么?
是的,就像在推送起源中一样。如果它运行多次,则不会发生任何事情。我还有一个 git push -f 别名设置为 git pf,所以一旦源已经被推送,我就会使用它。
djanowski's comment,可以直接使用HEAD
B
Beasleydotcom

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

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

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


j
jchavannes

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

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

现在每当你得到:

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

赶紧跑:

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

你可以走了


T
TTT

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}

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


i
inderpreet99

oh-my-zsh's git plugin 已将其别名为 gpsup。这会将上游推送并设置到分支。一口气!

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


T
Thorkil Værge

在 git 2.37.0 或更高版本中,您可以告诉 git 自动设置远程。这是用

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

然后你可以只写 git push 它将推送到默认遥控器。


当然。我只是觉得你的回答有点太冗长了。
这个答案应该涵盖 90-99% 的人对此功能的使用。如需更深入的解释,请参阅@VonC 的答案。
R
Rolf

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

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

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

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


o
ourmaninamsterdam

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


o
om471987

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

vim ~/.bash_aliases

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

节省

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

L
Loren

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

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

Original Post


M
Maxwell s.c

我只想做这样的事情:

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

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

alias push="git push -u origin HEAD"

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


B
Benny K

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

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

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

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


T
Tom Warner

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

通过创建本地正确跟踪的远程分支,让别名可以执行诸如“使 git push 以应有的方式工作”之类的操作肯定会有所帮助。但是,当您忘记使用它们或经历不同的工作流程时,这些都对您没有帮助。

这是一个 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 there
        git pull
    else
        if [[ $(git ls-remote --heads origin $head) ]]; then #there is an upstream branch existing with the same name as our branch
            git branch --set-upstream-to origin/$head #set merge target to upstream branch with same name
            git pull
        else #fail with explanation
            echo "Branch $head has no upstream or merge target! You will likely have to push first, or manually configure it"
            return 1
        fi
    fi
}

L
Lucas Wiman

显然没有支持的方式来覆盖 git 命令的默认选项。根据 this answerDefine git alias with the same name to shadow original command,我们可以覆盖 bash 中 git push 的行为以始终调用 git push -u。将以下内容放入您的 ~/.bash_profile 文件中,它应该等效于每次推送时运行 --set-upstream 。

function do_git {
  cmd=$1
  shift
  myArgs=( "$@" )

  if [ "$cmd" == "push" ]; then
    myArgs=( "-u" "${myArgs[@]}" )
  fi
  myArgs=( "$cmd" "${myArgs[@]}" )

  $(which git) "${myArgs[@]}"
}
alias  git='do_git'