如何轻松将本地Git分支推送到具有不同名称的远程分支?

285

我一直在想是否有一种简单的方法可以推送和拉取一个本地分支到一个名字不同的远程分支,而不必总是指定两个名称。

例如:

$ git clone myrepo.git
$ git checkout -b newb
$ ...
$ git commit -m "Some change"
$ git push origin newb:remote_branch_name

现在如果有人更新了远程分支(remote_branch_name),我可以:

$ git pull

而且一切都被合并/快进了。但是,如果我在我的本地“newb”中进行更改,我就不能:

$ git push

相反,我必须:

% git push origin newb:remote_branch_name

看起来有点傻。如果git-pull使用git-config branch.newb.merge来确定从哪里拉取,为什么git-push不能有类似的配置选项呢?是否有一个简便的方法,还是我应该继续走冗长的路线?

10个回答

287

在进行初始推送时,添加 -u 参数

git push -u origin my_branch:remote_branch

后续的推送会去你想要的地方。

编辑:

根据评论,那只是设置拉取。

git branch --set-upstream

应该这样做。


13
-u 命令只是设置了上游分支,而根据问题描述,上游分支已经被设置。为了让 push 命令遵循上游分支设置,他需要将 push.default 设置为 upstream,因为默认情况下只有 pull 命令会这样做。请注意保持原意,并简化语言以提高易懂性。 - Brian Campbell
3
似乎这并不起作用——至少对于较新版本的 git 不起作用。 - Thomas Watson
1
git branch --set-upstream 只设置了拉取设置,此后需要设置“pushRemote”。 - wheredidthatnamecomefrom
我认为 git branch --set-upstream 不是必要的。注意:我的 git --version 是 2.17.1。 - Gabriel Staples
我对这个问题有太多的疑问,所以我进行了大量的研究和实验,并在这里添加了自己的新答案:https://dev59.com/CW025IYBdhLWcg3w4qIx#70302053 - Gabriel Staples
显示剩余6条评论

119
当然可以,只需将push.default设置为upstream,即可将分支推送到它们的上游(由branch.newb.merge定义,这与pull拉取的相同),而不是将分支推送到名称匹配的分支(这是push.default的默认设置matching)。
git config push.default upstream

请注意,在Git 1.7.4.2之前,这个被称为tracking而不是upstream,所以如果你使用的是旧版本的Git,请使用trackingpush.default选项是在Git 1.6.4中添加的,因此如果您使用的是比那更旧的版本,则根本没有此选项,并且需要明确指定要推送到的分支。


就是这样!这适用于所有正在跟踪的分支,但没关系。谢谢! - jmacdonagh
我很想知道是否有一个简写来表示我已经检出的分支名称。我可能只想要 git push buildserver .:test_this,其中 . 应该是本地分支名称,而我不一定知道它是什么。我当然可以查找它,但如果有一个像点一样的简写来表示它,那就太棒了。 - Frederick Nord
2
@FrederickNord,你要找的是“HEAD”这个简写。如果你处于分离头状态,HEAD指向特定的提交,否则它指向当前检出的分支。 - Brian Campbell
谢谢!这对我修复了 Updates were rejected because a pushed branch tip is behind its remote 错误。我的本地仓库是最新的,但名称只是有所不同。 - canhazbits
这会影响到你所有仓库中所有分支的push行为。你可以使用--local参数将其限制在一个仓库中,但如果只针对单个分支,请参考这里 - Tom Hale

30

这个由Adam发布的指令已经被弃用。您可以使用以下指令:

git branch --set-upstream-to origin/my_remote_branch my_local_branch

my_local_branch的上游分支设置为origin/my_remote_branch

7
你能提供一个关于"-u"被弃用的信息的链接吗?关于推送操作的最新文档在git-scm.com中似乎表明它仍然可用。谢谢您的提前帮助,对读者来说跟进获取更多信息可能非常有帮助。 - Kay V
同意@KayV的观点,特别是当我尝试创建一个与本地分支名称不同的新远程分支时,我收到了这条消息:'如果您计划推出一个将跟踪其远程对应项的新本地分支,则可能希望在推送时使用“git push -u”来设置上游配置。' - FBB
这仅适用于fetchmergepull操作。有关每个分支的push配置,请参阅此答案 - Tom Hale

23

如何轻松地将本地Git分支推送到具有不同名称的远程分支?

概述:

以下是您通常需要的关键命令的简短摘要:

# push from your local `branch2` to a remote `branch1` (push to a branch with
# a different name) on the remote named `origin`
git push -u origin branch2:branch1
# pull from a remote branch `branch1` into your currently-checked-out branch
# (which could have a different name--ex: `branch2`)
git pull origin branch1

# Set your upstream to something new in case you want to change it; ex: set your
# currently-checked-out branch (perhaps `branch2`) to track `branch1` on the 
# remote named `origin`
git branch -u origin/branch1
# Unset your upstream
git branch --unset-upstream

# See what your upstream is currently set to
git branch -vv

详情:

以下内容按照顺序逐一介绍:

  1. 将代码推送到另一个分支
  2. 从另一个分支拉取代码
  3. 设置和取消上游分支跟踪

这里有太多不完整和部分回答,让我有很多问题和不满意之处。因此,在经过大量努力、研究和实验后,我尝试提供一个完整的解决方案。

1. 将本地分支推送到具有不同名称的远程分支

将本地的branch2推送到远程的branch1,您必须像这样指定两个分支:

# Push from local `branch2` to remote `branch1`
git push origin branch2:branch1

# General form: push from local `from_branch` to remote `to_branch`. 
# - Watch out!: see also the additional explanations and NB note below!
git push <remote> <from_branch>[:to_branch]

请注意,我在上面的一般形式中写的方括号表示:to_branch部分是可选的。我的意思是,如果要从一个名称为本地分支推送到一个不同名称的远程分支,则该部分是不可选的,但作为一般的git命令,如果您不包括:to_branch部分,该命令将运行,这意味着在这个意义上它是可选的。但是,这可能会产生意想不到的结果!例如,请看下面的命令:
# (push to a remote branch with the **same name** as the local branch)

# Reduced **and confusing** form: this pushes from local `branch2` (even if you
# don't currently have it checked-out!) to remote `branch2`.
git checkout branch3 
git push origin branch2          # Push from local branch2 to remote branch2

你可能当前正在使用本地的branch3分支,并认为执行git push origin branch2命令会将你的本地branch3推送到远程的branch2,因为你在本地系统上已经检出了branch3,但是实际情况并非如此!相反,git push origin branch2命令会将你的本地branch2分支推送到远程的branch2,即使你没有检出branch2分支也是如此!因此,git push origin branch2与以下命令等价:
# These 2 commands are **exactly identical**! The 1st cmd is the short form
# of the 2nd. 
git push origin branch2          # Push from local branch2 to remote branch2
git push origin branch2:branch2  # Push from local branch2 to remote branch2

上述命令的简写形式会导致非常混乱的行为,如果您认为它会从当前签出的分支推送。以下是对上述行为进行总结的Nota bene注意事项:
一般格式git push <remote> <from_branch>[:to_branch]中,如果您没有使用:to_branch指定远程TO分支,则假定它与本地FROM分支from_branchremote上具有相同的名称!这意味着,如果您只键入git push origin branch2而不是git push origin some_other_branch:branch2,它将从您本地的branch2向远程的branch2推送,即使您在运行命令时未签出branch2!如果您认为键入git push origin branch2已经告诉了您当前签出的分支some_other_branch向远程推送到branch2,实际上本地的branch2被推送到了远程的branch2,这可能非常令人困惑。
一般格式(git push <remote> <from_branch>[:to_branch])的文档很难找到,但实际上可以在man git push页面的顶部,在"<refspec>..."部分找到:

参数<refspec>的格式是一个可选的加号+,后跟源对象<src>,后跟冒号:,后跟目标引用<dst>

然后稍后又说:

可以省略::<dst>部分 - 这样的推送将更新<src>通常在命令行上没有任何<refspec>更新的引用。

我认为这份文档不直观且非常难以理解,但如果有一些示例和我的上述解释,就会容易理解。
更好的形式的git push:您还可以同时设置上游分支和推送。
# Push from local `branch2` to the remote `branch1`, while also at the same time
# setting `branch2` to track `origin/branch1` as the upstream
git push -u origin branch2:branch1
# OR (same thing)
git push --set-upstream origin branch2:branch1
# General form
git push -u <remote> <from_branch>[:to_branch]

作为上述命令的输出的一部分,您应该看到:
Branch 'branch2' set up to track remote branch 'branch1' from 'origin'.
为了更清晰地说明正在发生的事情,需要知道上面的任何一个命令都等同于这两个单独的命令:
git push origin branch2:branch1
git branch -u origin/branch1

现在,要查看你的分支上游分支当前设置为什么,请运行双重详细 (-vv) git branch 命令:

git branch -vv

示例输出:
在这里,您可以看到上游分支是origin/master,这意味着远程命名为originmaster分支:

* master b2f0466 [origin/master] c/array_filter_and_remove_element.c: add O(n) in-place solution

注意:

  1. -vv 表示“双倍冗长”。这意味着它不仅会详细地打印 git branch,而且是双倍冗长或者额外冗长。现在打印的“额外冗长”内容包括方括号中的上游分支,如上所示:[origin/matser]
  2. 您可以使用 git remote -v 查看所有远程仓库。上面的示例中显示的是 origin 仓库。

2. 从具有不同名称的远程分支拉取到本地分支

[如果您已经在本地检出了分支 branch2,则建议这样做!]从名为 origin 的远程仓库的 branch1 分支拉取到本地的 branch2 分支,您必须指定要拉取的远程分支,如下所示:

# THIS ASSUMES YOU ARE ALREADY CHECKED-OUT ON BRANCH `branch2`!

git pull origin branch1
# General form
git pull <remote> [from_branch]

您也可以指定两个分支,但在这种情况下,我不太确定差异是什么
git pull origin branch1:branch2

# The general form seems to be:
git pull <remote> <from_branch>[:to_branch]
以下命令只有在远程和本地分支名称相同时才有效!(因此它并没有回答这个 Stack Overflow 问题)。如果您还没有检出分支some_branch,则建议使用此命令!
# Pull FROM a remote branch named `some_branch` TO a local branch named
# `some_branch`, while you do NOT have `some_branch` locally checked-out.
git fetch origin some_branch:some_branch
# General form
git fetch <remote> <from_branch>:<to_branch>

# The above is a special form of `git fetch`, and (I believe) requires that 
# `from_branch` and `to_branch` are **the same branch name**. It is roughly 
# equivalent to the following *several* commands:
git checkout any_other_branch
# this `git fetch` cmd updates the **locally-stored**, hidden, remote-tracking
# branch named `origin/some_branch` with the latest changes from the branch
# by this name stored on the remote server named `origin`
git fetch origin some_branch 
git checkout some_branch
git merge origin/some_branch  # merge `origin/some_branch` into `some_branch`
git checkout any_other_branch # go back to the branch we started on

注:

  1. git pull 没有 -u 选项,与 git push 不同。
  2. 查看我的另一个答案:如何在 GitHub 上更改 PR 的所有者/如何接管开放的 GitHub PR
  3. git fetch origin some_branch:some_branch 命令中两次使用了相同的 some_branch 名称。它们之间的区别是:只有 git fetch origin some_branch 更新本地隐藏的远程跟踪分支 origin/some_branch,该分支存储在名为 origin 的远程服务器上,而 git fetch origin some_branch:some_branch 不仅更新该分支,还会将这些更改更新到本地可见的 some_branch 分支中。
    1. 如果您感到困惑,您需要了解每个名称为 some_branch 的分支实际上可以拆分成多达 3 个分支:1)本地分支 some_branch,2)名为 origin 的远程服务器上的远程分支 some_branch,以及 3)本地隐藏的远程跟踪分支 origin/some_branch。请阅读此处以获取更多信息。和我第一次学习这个“3 个分支”概念的地方:如何在本地和远程删除 Git 分支?。另请参见该答案下面的 我的评论

3. 配置本地分支以跟踪或取消跟踪远程分支

您可以使用上面显示的 git push -u 命令,在 推送时同时将本地分支 branch2 设置为跟踪上游分支 branch1

您还可以像这样将本地分支 branch2 设置为跟踪上游分支 branch1

# Set branch2 to track origin/branch1 (`branch1` on remote `origin`)
git branch --set-upstream-to=origin/branch1 branch2
# OR (same thing as just above)
git branch -u origin/branch1 branch2
# General form
git branch -u <remote>/<to_branch> [from_branch]

# OR, same as above if the currently-checked-out branch is `branch2`
git branch --set-upstream-to=origin/branch1
# OR (same thing as just above)
git branch -u origin/branch1
# General form
git branch -u <remote>/<to_branch>

要取消 branch2 的上游分支设置,这样它就不再跟踪以前设置的上游分支(在上面的示例中为 origin/branch1 ),请运行以下命令:

git branch --unset-upstream branch2
# OR, same as above if the currently-checked-out branch is `branch2`
git branch --unset-upstream

如上所示,要查看您的分支当前设置为哪个上游分支,请运行双重详细 (-vv) 的 git branch 命令:

git branch -vv

参考文献:

  1. 我最初学习 git push -u origin local_FROM_branch:remote_TO_branch 语法的地方:@Adam Dymitruk的答案
  2. https://devconnected.com/how-to-set-upstream-branch-on-git/
  3. 如何在本地和远程删除Git分支?

我写过的相关git主题:

  1. 初级:
    1. 从另一个分支在Git中创建分支
  2. 中级:
    1. 如何挑选多个提交
  3. 高级:
    1. 如何从另一个分支获取一个文件?
    2. 根据Git,"我们"和"他们"是谁?

谢谢,你的回答非常详细,但在短时间内有点难以理解:(例如,即使您没有在本地检出from_branch,也可以运行命令!如果您认为您刚刚告诉您当前检出的分支推送到远程的某个分支,而实际上是该某个分支的本地副本(您当前未检出)被推送到远程,这可能会非常令人困惑。)这部分可以更简洁一些吗? - Lan Si
1
@LanSi,这确实是一个非常令人困惑的话题,对我来说很难解释清楚。我更新了我的答案,试图澄清并使其更容易理解。如果现在更容易跟进,请告诉我。 - Gabriel Staples

6
如何在Git上将代码推送到不同名称的分支?
通常情况下,您会将本地分支推送到相同名称的远程分支 - 但并非总是如此。 要将代码推送到不同名称的分支上,您只需要指定要推送的分支和要推送到的分支的名称,两者之间用冒号(:)隔开。
例如,如果您想将名为“some-branch”的分支推送到“my-feature”分支:
(some-branch)$ git push origin some-branch:my-feature
Total 0 (delta 0), reused 0 (delta 0)
To github.com:johnmosesman/burner-repo.git
 + 728f0df...8bf04ea some-branch -> my-feature

如何将所有本地分支推送到远程

通常情况下,您不需要经常从本地推送所有分支到远程,但如果需要,您可以添加 --all 标志:

(main)$ git branch
* main
  my-feature

(main)$ git push --all
...
To github.com:johnmosesman/burner-repo.git
   b7f661f..6e36148  main -> main
 * [new branch]      my-feature -> my-feature

2
这似乎是最新的最佳答案。 - Dror Bar

4

是的,有一种配置选项可以使git默认推送到上游分支。

使用以下语句,这样您就不必每次都执行git push origin local:remote

# Set remote branch with a different name as an upstream branch 
# for local branch currently checked out
git branch --set-upstream-to origin/remote_branch_name

# Change the default behavior for git-push (see manpage for git-config)
git config push.default upstream

# Now git will push to the upstream branch by default
git push

将当前分支的上游设置为具有不同名称的远程分支后,您需要更改git push的默认行为为upstream(请参见git-config的man页面)。 现在,git push将遵循这些规则并推送到设置的上游。

这应该是被接受的答案,因为它是唯一一个解决了以下两个问题的答案:1)本地分支需要设置为跟踪远程分支;2)还需要设置push的默认行为。此外,它用尽可能少的词语解释了解决方案。 - Codebird

2

推送并创建一个临时远程分支

如果你想要:

  • 将当前分支以新的名称推送到远程库,但是:
  • 不改变当前分支的远程跟踪分支,并且:
  • 不创建一个本地分支以新的名称。

那么只需要执行以下简单操作:

git push origin HEAD:temp-branch-name

注意:您可以将HEAD替换为任何其他分支或提交ID,以代替推送。


0
两个选项:
1. 将所有存储库的分支推送到它们通过push.default = upstream获取拉取的位置。 2. 使用remote.<name>.push更改单个分支。
要使您的所有存储库分支都推送到它们拉取的分支上,请使用以下命令:
git config --local push.default upstream

注意:这将影响其他分支。
设置单个分支的远程推送对(示例:本地mainorigin/master):
1. 设置分支的远程连接 ``` git branch --set-upstream-to origin ```
2. 设置远程推送映射 ``` git config --local remote.origin.push main:master ```

0
如果你在本地分支有一堆文件想要保存到另一个分支,有一个很酷的方法可以做到。首先使用git stash命令保存所有修改过的文件(这是针对整个代码库的),然后使用git checkout remoteBranchYouWant命令切换到你想要的远程分支,接着使用git stash pop命令将之前保存的修改应用到新切换的分支上。现在你可以根据需要提交并推送这些修改到新的分支了。

0

这是我使用过的流程。

git clone original-repo-url
git remote rename origin upstream
git remote add origin new-repo-url

现在你的新仓库将会是“origin”,原始仓库则是“upstream”。通过运行git remote -v来确认它。(顺便说一句:Upstream用于从原始仓库获取内容,以便保持本地副本与你想要贡献的项目同步,而origin用于拉取和推送,因为你可以向自己的仓库做出贡献)。

git push origin master

现在你的新远程仓库的主分支(在Github上)将与原始主分支同步,但它不会有任何功能分支。

git rebase upstream/branch-name
git push origin master

Rebase是一种智能合并。然后再次推送到主分支,你将会在新的仓库中看到选择的功能分支作为主分支。
可选:
git remote rm upstream
git remote add upstream new-repo-url

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