How can I push a local Git branch to a remote with a different name easily?
How can I push a local Git branch to a remote with a different name easily?
Summary:
Here is a short summary of just the key commands you need in general:
# 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
Details:
The following sections are covered below, in this order:
- Pushing to another branch
- Pulling from another branch
- Setting and unsetting an upstream branch to track
There are too many incomplete and partial answers here which leave me with a lot of questions and a lot to be desired. So, after a bunch of effort and research and experimenting, here is my attempt at providing a complete solution.
1. Pushing from your local branch to a remote branch with a different name
To push FROM your local branch2
TO remote branch1
, you must specify both branches like this:
# 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]
Notice, however, that the square brackets I have written in the general form above indicate the :to_branch
part is optional. What I mean is that to push from a local branch with one name to a remote branch with a different name, that part is NOT optional, but, as a general git command, the command will run if you do not include the :to_branch
part, meaning it is optional in that sense. But, it may produce unexpected results! Take a look at this command, for example:
# (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
You might have local branch3
currently checked-out, and think that git push origin branch2
will push your local branch3
to the remote branch2
, since you have branch3
currently checked-out on your system, but this is NOT what will happen! Rather, git push origin branch2
will push your local branch2
to your remote branch2
, again, even if you do NOT have branch2
currently checked-out! git push origin branch2
is therefore an equivalent short-hand of this:
# 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
The short form of the cmd just above produces very confusing behavior if you think it will push from your currently-checked-out branch instead. Here is a Nota bene note summarizing the behavior described above:
NB: In the general form git push <remote> <from_branch>[:to_branch]
, if you don't specify the remote TO branch with :to_branch
, it is assumed to be the same name as your local FROM branch, from_branch
, on the remote
! This means if you type only git push origin branch2
instead of git push origin some_other_branch:branch2
, it pushes FROM your local branch2
TO the remote copy of branch2
, EVEN IF YOU DIDNT HAVE branch2
locally checked-out at the time of running the command! This can be VERY CONFUSING if you thought typing git push origin branch2
had just told your currently-checked out branch, some_other_branch
, to push to branch2
on the remote and instead, the local branch2
got pushed to the remote branch2
.
The documentation for the general form (git push <remote> <from_branch>[:to_branch]
) is hard to find, but it's actually found in the man git push
pages near the top under the "<refspec>...
" section:
The format of a
<refspec>
parameter is an optional plus+
, followed by the source object<src>
, followed by a colon:
, followed by the destination ref<dst>
.
And then later:
:<dst>
part can be omitted—such a push will update a ref that<src>
normally updates without any<refspec>
on the command line.
I think this documentation is non-intuitive and very difficult to understand, however, without some examples and my explanation above.
[BETTER FORM OF git push
] You can also set the upstream branch at the same time as pushing:
# 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]
As part of the output of the command above, you should see:
Branch 'branch2' set up to track remote branch 'branch1' from 'origin'.
To make it obvious what is happening there, know that either of the two commands just above are equivalent to these two separate commands:
git push origin branch2:branch1
git branch -u origin/branch1
Now, to view what your branch's upstream branch is currently set to, run the double-verbose (-vv
) git branch
cmd:
git branch -vv
Sample output:
Here you can see that the upstream branch is origin/master
, which means the master
branch on the remote named origin
:
* master b2f0466 [origin/master] c/array_filter_and_remove_element.c: add O(n) in-place solution
Notes:
-vv
above means "double verbose". This means it will printgit branch
not just verbosely, but double verbosely, or extra verbosely. The "extra verbose" content now printed includes the upstream branch in square brackets, as shown above:[origin/matser]
.- You can view all your remotes with
git remote -v
.origin
is the remote shown in the examples above.
2. Pulling from a remote branch with a different name to your local branch
[Recommended if you already have branch branch2
checked-out locally!] To pull FROM branch1
on the remote named origin
, TO branch2
, you must specify the remote branch to pull from, like this:
# THIS ASSUMES YOU ARE ALREADY CHECKED-OUT ON BRANCH `branch2`!
git pull origin branch1
# General form
git pull <remote> [from_branch]
You can also specify both branches, but I'm not entirely sure what the difference is in this case:
git pull origin branch1:branch2
# The general form seems to be:
git pull <remote> <from_branch>[:to_branch]
The following command only works if the remote and local branches have the same name! (therefore it does NOT answer this Stack Overflow question). This command is recommended if you do NOT already have branch some_branch
checked-out!
# 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
Notes:
- Unlike
git push
,git pull
does NOT have a-u
option. - See also another of my answers: How to change the owner of a PR on GitHub / How to commandeer an open GitHub PR
- The
git fetch origin some_branch:some_branch
command is done with the samesome_branch
name used twice--in both locations in the command. The difference is simply thatgit fetch origin some_branch
only updates the locally-stored, hidden, remote-tracking branch namedorigin/some_branch
with the latest changes from the branch by this name stored on the remote server namedorigin
, whereasgit fetch origin some_branch:some_branch
does that PLUS also updates the locally-stored visiblesome_branch
with those changes too.- If you feel confused about this, you need to learn that for every 1
some_branch
you think you have, you actually have up to 3 branches: 1) a local branchsome_branch
, 2) a remote branchsome_branch
on a remote server namedorigin
, and 3) and locally-stored, hidden, remote-tracking branch namedorigin/some_branch
. Read here for more info. and for where I first learned this concept of 3 branches per branch: How do I delete a Git branch locally and remotely?. See also my comment here, under that answer.
- If you feel confused about this, you need to learn that for every 1
3. Configuring your local branch to track or untrack a remote branch
You can set your local branch named branch2
to track an upstream branch named branch1
at the same time as pushing by using the git push -u
cmd shown above.
You can also set your local branch named branch2
to track an upstream branch named branch1
like this:
# 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>
To UNset your upstream branch for branch2
, so it no longer tracks the previously-set upstream branch (which was origin/branch1
in the examples above), run this:
git branch --unset-upstream branch2
# OR, same as above if the currently-checked-out branch is `branch2`
git branch --unset-upstream
And again, as already shown above, to view what your branch's upstream branch is currently set to, run the double-verbose (-vv
) git branch
cmd:
git branch -vv
References:
- Where I first learned the
git push -u origin local_FROM_branch:remote_TO_branch
syntax: @Adam Dymitruk's answer - https://devconnected.com/how-to-set-upstream-branch-on-git/
- How do I delete a Git branch locally and remotely?
Related git
topics I've written about:
- BEGINNER:
- Create a branch in Git from another branch
- INTERMEDIATE:
- How to cherry-pick multiple commits
- ADVANCED:
- How to get just one file from another branch?
- Who is "us" and who is "them" according to Git?
Sure. Just set your push.default
to upstream
to push branches to their upstreams (which is the same that pull
will pull from, defined by branch.newb.merge
), rather than pushing branches to ones matching in name (which is the default setting for push.default
, matching
).
git config push.default upstream
Note that this used to be called tracking
not upstream
before Git 1.7.4.2, so if you're using an older version of Git, use tracking
instead. The push.default
option was added in Git 1.6.4, so if you're on an older version than that, you won't have this option at all and will need to explicitly specify the branch to push to.
The command by Adam is now deprecated. You can use:
git branch --set-upstream-to origin/my_remote_branch my_local_branch
to set the upstream branch of my_local_branch
to origin/my_remote_branch
.
When you do the initial push add the -u parameter:
git push -u origin my_branch:remote_branch
Subsequent pushes will go where you want.
EDIT:
As per the comment, that only sets up pull.
git branch --set-upstream
should do it.