442

If there is a repository that I only have git:// access to (and would usually just push+pull), is there a way to rename branches in that repository in the same way that I would do locally with git branch -m?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kdt
  • 27,905
  • 33
  • 92
  • 139
  • 50
    The linked "duplicate" question asks to rename a branch "both locally and remote". This question, however, only asks how to rename branches remotely, which allows for a simplification. This is what I do to rename a branch on the server without the need to checkout and / or create a local branch: `git push origin origin/old_name:refs/heads/new_name && git push origin :old_name`. – sschuberth Nov 25 '13 at 09:43
  • 1
    @sschuberth: you can give both commands in one go. And this really should be the answer to this question. – Joachim Breitner Dec 03 '13 at 08:50
  • 2
    @JoachimBreitner You're right, I did that optimization already in [this script](https://github.com/sschuberth/dev-scripts/blob/master/git/git-rename-remote-branch.sh) of mine. – sschuberth Dec 03 '13 at 11:30
  • 1
    @sschuberth, you should post your comment as an answer, since I like it better than the others below. – phatmann Jan 22 '14 at 21:34
  • [Done](http://stackoverflow.com/a/21302474/1127485). – sschuberth Jan 23 '14 at 07:58
  • Possible duplicate of [How do I rename a local Git branch?](https://stackoverflow.com/questions/6591213/how-do-i-rename-a-local-git-branch) – Vineet Jain Aug 26 '17 at 16:10
  • I tried all the below methods. Essentially, you cannot rename the remote branch. All below methods are deleting old remote branch and create a new remote one. If you do so in gitlab, the old branch/MR will be closed and you have to create a new MR. – new2cpp Feb 23 '18 at 07:09
  • Related: [Rename master branch for both local and remote Git repositories](https://stackoverflow.com/questions/1526794/rename-master-branch-for-both-local-and-remote-git-repositories) – Vadzim Oct 01 '19 at 10:23
  • Also related: [How do I rename both a Git local and remote branch name](https://stackoverflow.com/q/30590083/3216427) – joanis Nov 17 '21 at 13:30

10 Answers10

508

You just have to create a new local branch with the desired name, push it to your remote, and then delete the old remote branch:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

Then, to see the old branch name, each client of the repository would have to do:

$ git fetch origin
$ git remote prune origin

NOTE: If your old branch is your main branch, you should change your main branch settings. Otherwise, when you run $ git push origin :old-branch-name, you'll get the error "deletion of the current branch prohibited".

Community
  • 1
  • 1
Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85
  • If new name and old name are the same, won't this just delete the branch? If you switch the order of the pushes, I think it's a bit safer. – Mysterious Dan Nov 07 '14 at 21:00
  • 8
    Well, if the old and new names are the same, then it means you don't need to rename the branch, so there is no point running the command in the first place ;-) – Sylvain Defresne Nov 08 '14 at 20:25
  • 9
    Sure. I just mean that if you're calling this in an automated way (as a function part of some other script) you might as well not have it do the wrong thing if you can avoid it. – Mysterious Dan Nov 10 '14 at 16:02
  • An automated tool can easily check the names to avoid this though. – Earth Engine May 01 '15 at 02:50
  • 9
    Dan's way: reorder the commands so they always just work. Earth Engine's way: always remember to check, or you lose data. I know which one I'd pick. – Doradus Oct 27 '15 at 15:01
  • Followed the similar step. But I renamed the local branch then push it. Thank you for the idea! @SylvainDefresne – KarenAnne Jan 21 '16 at 07:55
  • 1
    To make this an alias so you can run "git mvbranch oldbranch newbranch", put this in ~/.gitconfig [alias] block: `mvbranch = "!moveit() { git branch -m $1 $2; git push origin :$1; git push --set-upstream origin $2; }; moveit"` – mahemoff Feb 03 '16 at 18:44
  • 2
    The users can just run : `git fetch origin --prune` (to effectively fetch the new branches and also get rid of the references no longer on the remote). – DolphinDream Feb 19 '16 at 14:49
  • 4
    Can use `-d` or `--delete` instead of `:` in newer versions of git. – Zitrax Jun 02 '16 at 09:38
  • @SylvainDefresne, what if you are trying to change the name of a remote branch that is the active branch of the remote repository? If you dont have access to the remote bare repo (such as through github), how do you change the main branch settings remotely? – alpha_989 Apr 11 '18 at 16:16
  • I followed the steps in solution provided but my old branch which I supposed to delete, is still there. :( – ShaileshDev Feb 04 '21 at 07:13
320

If you really just want to rename branches remotely, without renaming any local branches at the same time, you can do this with a single command:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

I wrote this script (git-rename-remote-branch) which provides a handy shortcut to do the above easily.

As a bash function:

git-rename-remote-branch() {
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : ${FUNCNAME[0]} <remote> <old name> <new name>"
    echo "Example   : ${FUNCNAME[0]} origin master release"
    return 1 
  fi

  git push $1 $1/$2\:refs/heads/$3 :$2
}

To integrate @ksrb's comment: What this basically does is two pushes in a single command, first git push <remote> <remote>/<old_name>:refs/heads/<new_name> to push a new remote branch based on the old remote tracking branch and then git push <remote> :<old_name> to delete the old remote branch.

sschuberth
  • 28,386
  • 6
  • 101
  • 146
  • 11
    For those who would like an alias of that command: rename = "!f() { git push origin origin/$1:refs/heads/$2 :$1; } ; f" this can be used as > git rename – Jonathan Schmidt Sep 03 '14 at 12:08
  • That is the only working solution if you already set your local branch to track the remote one with its old name. – Julien Carsique Jun 10 '15 at 08:45
  • 35
    For those curious about what this command actually means it's essentially 2 pushes `git push /:refs/heads/` means push a new remote that uses the old remote as a src **then** `git push [space]:` means delete the old remote – ksrb Sep 01 '15 at 03:42
  • 3
    Why do you need to use `refs/heads/name`? Can't you just use `name` directly, making the first command `git push /:`? – Drew Noakes Dec 20 '16 at 09:20
  • 6
    No, because the remote branch `` does not exist yet. If the branch does not exist, Git requires you to use the full name as otherwise `` could also refer to a tag name. – sschuberth Dec 20 '16 at 09:24
  • 4
    We use this approach in our build system. The only caveat we encounter is if `refs/heads/` already exists. The delete still succeeds, resulting in `/` only being deleted. Some checking before hand can easily avoid this. – Apeiron Apr 26 '17 at 23:16
  • It must say `heads` (plural) in the `refs`. – sschuberth Sep 04 '17 at 12:00
  • @sschuberth Many thanks! I'm gonna delete my original comment. So I made a typo, wrote `head` instead of `heads`, and Git still said "created new branch" when in fact there are no new branches to be seen! – Rolf Sep 04 '17 at 12:02
  • 1
    They actually *were* created, just not in a namespace Bitbucket cares about. – sschuberth Sep 04 '17 at 12:03
  • 1
    They won't show up in any branch related command, as these only look at the `heads` namespace, at least by default. I was not saying it's specific to Bitbucket, I was just trying to explain *why* Bitbucket does not care about them, and why it's ok to do so. – sschuberth Sep 04 '17 at 12:08
  • 1
    @sschuberth i fixed the link to your script, which was broken... ever thought of contributing those to `git-extras` or something? looks quite useful! – anarcat Nov 10 '17 at 15:19
  • Thanks, I've approved the edit. But I guess this is not really sophisticated enough for `git-extras`. – sschuberth Nov 10 '17 at 15:26
  • 2
    @cupawntae: What's the reason you've escaped the colon? – sschuberth Jun 29 '20 at 16:07
  • @sschuberth short answer: zsh compatibility. Long answer: my zsh is too rusty to tell you exactly how it's interpreting `$2:r` but when I tried the function in zsh, it was eating the `:r` and so instead of `branch:refs/heads` I was getting `branchefs/heads`. I figured it was some sort of parameter expansion flag, and rather than go research it I took a punt and tried escaping the colon, which worked. Didn't know if it was a zsh-specific flag, but I did make sure to test the updated function in bash before updating the answer, and it seemed to work fine, so I made the edit. – CupawnTae Jun 29 '20 at 20:37
  • 1
    Danger! You must do a fetch from the remote before the pushes. Otherwise, the / remote-tracking ref that gets pushed might be outdated, and the new branch ends up at the point where you last fetched. – ak2 May 22 '22 at 07:12
  • Btw, just in case if you're initialized empty repository and set up origin - you will need extra fetch command before invoking rename. See https://stackoverflow.com/a/13928822/2338477 – TarmoPikaro Sep 16 '22 at 12:41
188

First checkout to the branch which you want to rename:

git branch -m old_branch new_branch
git push -u origin new_branch

To remove an old branch from remote:

git push origin :old_branch
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shashank Hegde
  • 2,533
  • 1
  • 18
  • 18
  • 14
    When you push the renamed branch (new_branch) to remote (origin) you should also set its upstream to track the branch with the new name (e.g. `git push -u origin new_branch`) otherwise the renamed branch (new_branch) will continue to track the origin/old_branch. And once you delete the remote old_branch, the new_branch will still track the origin/old_branch, albeit now that branch is gone. – DolphinDream Feb 19 '16 at 14:47
  • 1
    @DolphinDream I edited the answer to include your useful upstream change. – mVChr Sep 15 '16 at 18:51
11

Sure. Just rename the branch locally, push the new branch, and push a deletion of the old.

The only real issue is that other users of the repository won't have local tracking branches renamed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 1
    so when trying to delete master, I've tried $ git clone ../src $ cd src $ git branch notmaster $ git checkout notmaster $ git branch -d master $ git push ../src :master But it complains: The destination refspec neither matches an existing ref on the remote nor begins with refs/, and we are unable to guess a prefix based on the source ref. error: failed to push some refs to '../alpha/' The remote really does have a branch called master – kdt Jan 20 '11 at 23:43
4

To change the branch name follow the below steps:

  1. git branch -m old_branchname new_branchname
  2. git push origin :old_branchname new_branchname
  3. git push --set-upstream origin new_branchname

After that fetch the origin

  1. git fetch origin
  2. git remote prune origin
rNkL
  • 376
  • 3
  • 11
2

TL;DR

"Renaming" a remote branch is actually a 2 step process (not necessarily ordered):

  • deletion of the old remote branch (git push [space]:<old_name> as ksrb explained);
  • push into a new remote branch (difference between a couple of answers commands below).

Deleting

I use TortoiseGit and when I first tried to delete the branch through the command line, I got this:

$ git push origin :in
  • fatal: 'origin' does not appear to be a git repository

  • fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

This was likely due to pageant not having the private key loaded (which TortoiseGit loads automatically into pageant). Moreover, I noticed that TortoiseGit commands do not have the origin ref in them (e.g. git.exe push --progress "my_project" interesting_local:interesting).

I am also using Bitbucket and, as others web-based online git managers of the sort (GitHub, GitLab), I was able to delete the remote branch directly through their interface (branches page):

Delete branch Bitbucket

However, in TortoiseGit you may also delete remote branches through Browse References:

Browse References menu

By right-clicking on a remote branch (remotes list) the Delete remote branch option shows up:

TortoiseGit remote branch delete

Pushing

After deleting the old remote branch I pushed directly into a new remote branch through TortoiseGit just by typing the new name in the Remote: field of the Push window and this branch was automatically created and visible in Bitbucket.

However, if you still prefer to do it manually, a point that has not been mentioned yet in this thread is that -u = --set-upstream.

From git push docs, -u is just an alias of --set-upstream, so the commands in the answers of Sylvain (-set-upstream new-branch) and Shashank (-u origin new_branch) are equivalent, since the remote ref defaults to origin if no other ref was previously defined:

  • git push origin -u new_branch = git push -u new_branch from the docs description:

    If the configuration is missing, it defaults to origin.

In the end, I did not manually type in or used any of the commands suggested by the other answers in here, so perhaps this might be useful to others in a similar situation.

CPHPython
  • 12,379
  • 5
  • 59
  • 71
  • the problem is that your remote is not called `origin`. You have to name your remote as you get it from running the command `git remote`. Git works with `ssh` what implies that you're using public+private keys. I assume that the `Autoload Putty keys` of TortoiseGit is just autoloading the needed keys for you to do anything at all with your remote reference. Last thing is that `git push -u` is not an alias for pushing into a remote branch, it is an alias for pushing into a remote branch **that was created locally and its remote reference has not yet this branch**. – juanecabellob Mar 22 '18 at 09:21
  • 1
    @juancab `-u` is an alias of `--set-upstream` and "if the configuration is missing, it [defaults to `origin`](https://git-scm.com/docs/git-push#_description)". [Sylvain](https://stackoverflow.com/a/4754132/6225838) and [Shashank](https://stackoverflow.com/a/21300116/6225838) use this for **pushing into a _newly created_ remote branch**. The _key_ issue may have been due to _pageant_ not having it loaded when I tried `git push origin :in` on the shell. So I don't understand your downvote, I just pointed out mine and non-addressed details in other answers, explained them and solved them. – CPHPython Mar 22 '18 at 15:24
  • You are stating wrong things and much of this answer is unrelated to the question itself. If you are pointing out what did work for you, I encourage you to limit the answer to what it did work and if you really want to give an explanation, please inform yourself better. Btw: `-u` is an alias for `--set-upstream` but that is not an alias for pushing into a remote branch as you said. To push into a remote branch you uniquely need `git push `, and if it's not in the remote yet, you add `git push -u `. Therefore, `-u` is used to create a reference of the branch in the remote. – juanecabellob Mar 22 '18 at 17:44
  • 1
    @juancab perhaps what you deemed wrong was mostly the _alias_ phrasing or choice of words. I restructured my answer and rephrased it in order to provide a full explanation of the solution(s) I found to _rename_ a remote branch. – CPHPython Mar 23 '18 at 09:53
  • I would rephrase it further. It makes more sense now, but it is still too long. I would be more specific to the problem, i.e. state that for TortoiseGit users the proposed solutions won't work. You are telling a story and that's confusing and makes users avoid reading. I'll edit your answer with a proposition. – juanecabellob Mar 23 '18 at 15:48
1

I don't know if this is right or wrong, but I pushed the "old name" of the branch to the "new name" of the branch, then deleted the old branch entirely with the following two lines:

git push origin old_branch:new_branch
git push origin :old_branch
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • As far as I can tell, this is exactly what all the other answers does. Your answer is just more succinct. – Clearer Jun 07 '18 at 06:54
1

I don't know why but @Sylvain Defresne's answer does not work for me.

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

I have to unset the upstream and then I can set the stream again. The following is how I did it.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name
arthur bryant
  • 395
  • 5
  • 6
0

If you're using Github...

You can create a new branch based on old-name branch using the UI on github.com:

Branch Rename

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Pober Wong
  • 128
  • 1
  • 4
-4

Adding to the answers already given, here is a version that first checks whether the new branch already exists (so you can safely use it in a script)

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(the check is from this answer)

myzzzl
  • 13
  • 2
  • I would have used `git show-ref --quiet --verify -- refs/heads/$new_name` instead of `ls-remote | cut | sed | grep`. – Andy Jun 29 '17 at 19:15