884

I have the branch master which tracks the remote branch origin/master.

I want to rename them to master-old both locally and on the remote. Is this possible?

For other users who tracked origin/master (and who always updated their local master branch via git pull), what would happen after I renamed the remote branch?
Would their git pull still work or would it throw an error that it couldn't find origin/master anymore?

Then, further on, I want to create a new master branch (both locally and remote). Again, after I did this, what would happen now if the other users do git pull?

I guess all this would result in a lot of trouble. Is there a clean way to get what I want? Or should I just leave master as it is and create a new branch master-new and just work there further on?

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Albert
  • 65,406
  • 61
  • 242
  • 386
  • 2
    The recipe given in the accepted answer does apply to a branch of any name, but the caveats (as noted) do not, due to the (by default) special role of the _master_ branch in Git. – kynan Apr 18 '12 at 16:18
  • 3
    @kynan: I think I don't understand. What caveats do apply to master and don't apply on other branches? If it would be a branch named xy and other people have tracked that branch, how would that be different? – Albert Apr 19 '12 at 13:05
  • 4
    The caveat that you can't normally delete the remote master. That does not apply to Aristotle's answer though, so you might want to mark that as the accepted answer. You're correct, any `git push -f` affects the ability to `pull` from any remote tracking branch. – kynan Apr 19 '12 at 13:47
  • 1
    you can create a new branch `master-old` that points to the same commit as the previous `master` branch. Then you can overwrite the `master` branch with your new changes by doing a `merge` with the `ours` strategy. Doing a merge works when the remote does not allow non-fastforward changes. That also means other users won't have forced updates. – dnozay Jun 20 '14 at 17:30
  • 1
    @kynan `master` is only special as long as it's the only existing branch. As soon as you have more than one, all branches are on an equal footing. – jub0bs Sep 14 '14 at 10: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:09
  • Remote only solution without local manipulations is available in comments in https://stackoverflow.com/questions/4753888/renaming-branches-remotely-in-git – Vadzim Oct 01 '19 at 10:24

17 Answers17

649

The closest thing to renaming is deleting and then recreating on the remote. For example:

git branch -m master master-old
git push remote :master         # Delete master
git push remote master-old      # Create master-old on remote

git checkout -b master some-ref # Create a new local master
git push remote master          # Create master on remote

However, this has a lot of caveats. First, no existing checkouts will know about the rename - Git does not attempt to track branch renames. If the new master doesn't exist yet, git pull will error out. If the new master has been created. the pull will attempt to merge master and master-old. So it's generally a bad idea unless you have the cooperation of everyone who has checked out the repository previously.

Note: Newer versions of Git will not allow you to delete the master branch remotely by default. You can override this by setting the receive.denyDeleteCurrent configuration value to warn or ignore on the remote repository. Otherwise, if you're ready to create a new master right away, skip the git push remote :master step, and pass --force to the git push remote master step. Note that if you're not able to change the remote's configuration, you won't be able to completely delete the master branch!

This caveat only applies to the current branch (usually the master branch); any other branch can be deleted and recreated as above.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • 3
    branches are just a (name, hash) pair - nothing more, nothing less. There is the reflog on branches, but this is never exposed to remote clients. – bdonlan Oct 06 '09 at 21:03
  • 147
    I would create master-old on remote before deleting master on remote. I'm just paranoid. – Adam Dymitruk Aug 11 '10 at 16:58
  • No dice at second command: "remote: error: By default, deleting the current branch is denied, because the next remote: error: 'git clone' won't result in any file checked out, causing confusion. remote: error: remote: error: You can set 'receive.denyDeleteCurrent' configuration variable t remote: error: 'warn' or 'ignore' in the remote repository to allow deleting th remote: error: current branch, with or without a warning message. remote: error: remote: error: To squelch this message, you can set it to 'refuse'. remote: error: refusing to delete the current branch: refs/heads/master" – kdt Jan 21 '11 at 10:29
  • @kdt, the answer you seek is in the message you just pasted... But yeah, newer versions of git are unhappy about deleting the master branch. I'll update the example. – bdonlan Jan 21 '11 at 10:56
  • @AdamDymitruk no need to be paranoid unless you believe that the server receiving the push deleting the branch ref does something extra (which may be the case for GitHub). Git by default won't clean up unless you tell it to. – kynan Dec 09 '11 at 20:05
  • 6
    Aristotle's answer below allows you to do this without deleting the master, so I'd think that preferable. – Clay Bridges Mar 24 '12 at 23:43
  • 13
    it would be clear and SAFE if you can use `new-branch-name` and `old-branch-name` instead of `master`/`master-old`, thus this is a general problem. – Jaider Sep 18 '12 at 22:53
  • 2
    If the deleted branch (here: master) is not referenced by other branches, git might garbage collect all commits on that ... well ... “branch”. – Some git porcelain commands trigger a garbage collection. – Therefore: create the new name first (pointing to the same commit), then delete the old name. – Robert Siemer Jan 14 '15 at 12:35
  • `git push remote :master` > fatal: 'remote' 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. – vee Apr 27 '16 at 04:56
  • @vee, I had the same error - try `git push origin`. – Alex Barkun Feb 08 '17 at 08:54
  • @vee git has excellent auto-completion, just type `git push [TABULATOR]` – phil294 Feb 12 '17 at 17:32
  • with this recipe I am getting `! [remote rejected] master (refusing to delete the current branch: refs/heads/master) error: failed to push some refs to 'https://github.com/me/repo'` on `git push -f remote :master ` – Dima Lituiev Jan 05 '18 at 22:52
  • Step 2 fails: 'remote' does not appear to be a git repository – Jesse Barnum Sep 02 '20 at 16:52
  • @JesseBarnum You should replace 'remote' with the name of your remote repository. Conventionally is called origin. You can list your actual remotes using "git remote" – Jonathan Hartley Feb 22 '21 at 19:31
270

Assuming you are currently on master:

git push origin master:master-old        # 1
git branch master-old origin/master-old  # 2
git reset --hard $new_master_commit      # 3
git push -f origin                       # 4
  1. First make a master-old branch in the origin repository, based off of the master commit in the local repository.
  2. Create a new local branch for this new origin/master-old branch (which will automatically be set up properly as a tracking branch).
  3. Now point your local master to whichever commit you want it to point to.
  4. Finally, force-change master in the origin repository to reflect your new local master.

(If you do it in any other way, you need at least one more step to ensure that master-old is properly set up to track origin/master-old. None of the other solutions posted at the time of this writing include that.)

Aristotle Pagaltzis
  • 112,955
  • 23
  • 98
  • 97
  • 16
    This is better answer than "the answer", I agree, but for people who came here to just rename a branch (not explicitly master), the 3rd step doesn't make much sense. – knocte Aug 28 '12 at 23:22
  • It makes absolutely no difference to the answer whether you are on `master` or another branch. The question was badly titled though, it asks about a task more complex than *just* renaming a branch. – Aristotle Pagaltzis Aug 29 '12 at 08:12
  • 3
    This turned out to be the solution that worked for me. I was trying to replace master with another branch. I did a git log -1 origin/what_i_want_as_new_master to get the $new_master_commit for step 3. After the push (step 4), other devs would pull and get messages "your branch is ahead of master by 295 commits." To fix this I sent out an email letting them know to each run: git pull; git checkout some_random_branch; git branch -D master; git pull; git checkout master; Basically, they need to remove their local master and pull the new version otherwise they're at the wrong place locally. – nairbv Nov 14 '13 at 22:44
  • You could have done that far more easily: assuming they’re already on `master` then they could just do `git fetch && git reset --hard origin/master` to force their local `master` to be the same as the one on `origin`. I have documented this, as well as the more complex case where you have local commits on top of `master` that you want to keep, in http://stackoverflow.com/q/4084868 – Aristotle Pagaltzis Nov 17 '13 at 06:27
  • Make sure that the remote config file has "denyNonFastforwards = false" or you will get "remote: error: denying non-fast-forward refs/heads/master (you should pull first)" – gjcamann May 28 '14 at 13:57
180

With Git v1.7, I think this has changed slightly. Updating your local branch's tracking reference to the new remote is now very easy.

git branch -m old_branch new_branch         # Rename branch locally    
git push origin :old_branch                 # Delete the old branch    
git push --set-upstream origin new_branch   # Push the new branch, set local branch to track the new remote
Excalibur
  • 3,258
  • 2
  • 24
  • 32
  • 14
    An alternative to ```--set-upstream``` is as follows: Once you have your branch renamed locally and deleted on the origin, simply do: ```git push -u --all``` – lucifurious Jul 09 '13 at 17:36
  • 1
    What happens to the rest of the team after this is done? What should other team members do to switch to the new branch? – Michael Teper Jan 02 '14 at 16:31
  • 6
    This will not work with master branch, since git will not allow you to delete the remote master. – Alexandre Neto Jan 06 '14 at 16:23
  • 6
    @AlexandreNeto In this case you can execute the 3rd line before the 2nd, set the default branch to `new_branch` and then eventually delete the remote `master` with the 2nd line. – Tristan Jahier Feb 03 '15 at 20:00
  • 4
    Amazingly simple steps. This is the best answer of the question – siddhusingh Feb 20 '15 at 10:09
  • 1
    This is the most simple and working solution to rename a non master branch. Tested on git 2.4 and it works!! – haudoing May 11 '15 at 03:14
  • This also will work on master branch if your are using github. You just need to push new branch first and then in repository settings set is as default. Then you can delete master branch. – Alma Do May 22 '15 at 09:02
  • Will all the History of the old_branch be there in the new_branch (In case of doing this with master for the sake of clarity) – Stephan Kristyn Sep 02 '15 at 15:47
  • 21
    To delete the remote branch `git push origin --delete old_branch` is slightly more readable. – ThomasW Oct 14 '15 at 03:21
  • Yes, definitely best answer here. Always worth checking GitHub as well since they usually have the answer too: https://gist.github.com/lttlrck/9628955 – Belfield Jul 21 '17 at 10:40
42

There are many ways to rename the branch, but I am going to focus on the bigger problem: "how to allow clients to fast-forward and not have to mess with their branches locally".

First a quick picture: renaming master branch and allowing clients to fast-forward

This is something actually easy to do; but don't abuse it. The whole idea hinges on merge commits; as they allow fast-forward, and link histories of a branch with another.

renaming the branch:

# rename the branch "master" to "master-old"
# this works even if you are on branch "master"
git branch -m master master-old

creating the new "master" branch:

# create master from new starting point
git branch master <new-master-start-point>

creating a merge commit to have a parent-child history:

# now we've got to fix the new branch...
git checkout master

# ... by doing a merge commit that obsoletes
# "master-old" hence the "ours" strategy.
git merge -s ours master-old

and voila.

git push origin master

This works because creating a merge commit allows fast-forwarding the branch to a new revision.

using a sensible merge commit message:

renamed branch "master" to "master-old" and use commit ba2f9cc as new "master"
-- this is done by doing a merge commit with "ours" strategy which obsoletes
   the branch.

these are the steps I did:

git branch -m master master-old
git branch master ba2f9cc
git checkout master
git merge -s ours master-old
dnozay
  • 23,846
  • 6
  • 82
  • 104
  • 5
    Thanks! `git merge -s ours master-old` is the crucial piece that the other answers miss. Also, "easy to do" does not mean "easy to understand, or find out" which seems to be the case with much of git, but I digress. – Martin Vidner Jul 28 '16 at 14:50
  • 3
    I love the fact that no deletions are mentioned and that the transition for those working with clones of upstream is "seamless". Thank you! – Piotrek Nov 16 '16 at 03:16
  • 1
    Does this work if master has changes you don't want master-new? – Ethan Fischer Jun 15 '20 at 20:51
  • @EthanFischer Yes. The merge uses the "ours" strategy, which basically creates an empty merge. But that empty merge is enough to trick git into believing that it's a fast-forward push. – Double_A Mar 24 '23 at 11:08
38
git checkout -b new-branch-name
git push remote-name new-branch-name :old-branch-name

You may have to manually switch to new-branch-name before deleting old-branch-name

sigod
  • 3,514
  • 2
  • 21
  • 44
Treken
  • 389
  • 3
  • 2
12

I'm assuming you're still asking about the same situation as in your previous question. That is, master-new will not contain master-old in its history.* If you call master-new "master", you will effectively have rewritten history. It does not matter how you get into a state in which master is not a descendant of a previous position of master, simply that it is in that state.

Other users attempting to pull while master does not exist will simply have their pulls fail (no such ref on remote), and once it exists again in a new place, their pulls will have to attempt to merge their master with the new remote master, just as if you merged master-old and master-new in your repository. Given what you're trying to do here, the merge would have conflicts. (If they were resolved, and the result was pushed back into the repository, you'd be in an even worse state - both versions of history there.)

To answer your question simply: you should accept that sometimes there will be mistakes in your history. This is okay. It happens to everyone. There are reverted commits in the git.git repository. The important thing is that once we publish history, it is something everyone can trust.

*If it did, this would be equivalent to pushing some changes onto master, and then creating a new branch where it used to be. No problem.

Community
  • 1
  • 1
Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • Yea, it's the same problem, just was one idea how to solve it. But even if I would not do this branch-renaming, I was interesting if it would be possible. I thought such refs as "master" are only references to specific commits. I really don't want to change any history. I thought I would just point the master-reference to another head. This also means, I can never ever use a branch name again if I have ever used it before? – Albert Oct 06 '09 at 17:35
  • Indeed, branches are refs - pointers to commits. The thing is, we expect the head of a branch to evolve in a particular way (namely, always fast-forwarding). From the point of view of someone else, moving a branch in your public repo is the same as rewriting the history of the branch. It no longer points to a commit containing everything it used to. – Cascabel Oct 06 '09 at 19:16
10

The selected answer failed when I tried it. It throws an error: refusing to delete the current branch: refs/heads/master. I guess I'll post what works for me:

git checkout master             # If not in master already

git branch placeholder          # Create placeholder branch
git checkout placeholder        # Check out to placeholder
git push remote placeholder     # Push placeholder to remote repository

git branch -d master            # Remove master in local repository
git push remote :master         # Remove master from remote repository.

The trick is to check out to the placeholder right before pushing it to remote repository. The rest is self explanatory; deleting the master branch and push it to the remote repository should work now. Excerpted from here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
O.O
  • 7,179
  • 1
  • 34
  • 32
  • It would fail on git push remote :master if this is checked on remote side - you will see "remote: error:" as prefix in the error log lines. – rafalmag Apr 13 '15 at 15:17
2

OK, renaming a branch both locally and on the remote is pretty easy!...

If you on the branch, you can easily do:

git branch -m <branch>

or if not, you need to do:

git branch -m <your_old_branch> <your_new_branch>

Then, push deletion to the remote like this:

git push origin <your_old_branch>

Now you are done.

If you get an upstream error while you trying to push, simply do:

git push --set-upstream origin <your_new_branch>

I also created the image below to show the steps on a real command line. Just follow the steps and you would be good:

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alireza
  • 100,211
  • 27
  • 269
  • 172
2

Log in at the server, go to the Git directory and rename the branch in the bare repository.

This does not have all the problems associated with reuploading the same branch. Actually, the 'clients' will automatically recognize the modified name and change their remote reference.

Afterwards (or before) you can also modify the local name of the branch.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

What about:

git checkout old-branch-name
git push remote-name new-branch-name
git push remote-name :old-branch-name
git branch -m new-branch-name
1

This is the simplest and most 'readable' way I know of:

'Move' local branch using -m

git branch -m my_old_branch_name my_new_branch_name

Push the 'moved' branch to the remote, set 'upstream' using -u

git push origin -u my_new_branch_name

Setting 'upstream' essentially 'connects' your local branch to the remote, so that things like fetch, pull and push will work.

Delete the old branch from the remote

git push origin -D <old_name>

Your local branch is already gone, because you 'moved' it in the first step.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
0

You may do the following:

git -m master master-old #rename current master
git checkout -b master   #create a new branch master
git push -f origin master #force push to master

But force pushing is a bad idea if other people are sharing this repository. Force push will cause their revision history to conflict with the new one.

Riyafa Abdul Hameed
  • 7,417
  • 6
  • 40
  • 55
0

The following can be saved to the shell script to do the job:

For example:

remote="origin"

if [ "$#" -eq 0 ] # if there are no arguments, just quit
then
    echo "Usage: $0 oldName newName or $0 newName" >&2
    exit 1
elif
    [ "$#" -eq 1 ] # if only one argument is given, rename current branch
then
    oldBranchName="$(git branch | grep \* | cut -d ' ' -f2)" #save current branch name
    newBranchName=$1
else
    oldBranchName=$1
    newBranchName=$2
fi

git branch -m $oldBranchName $newBranchName

git push $remote :$oldBranchName # Delete old branch on remote
git push --set-upstream $remote $newBranchName # Add new branch name on remote and track it

Please note that here default remote name "origin" is hard-coded. You can extend the script to make it configurable!

Then this script can be used with Bash aliases, Git aliases or in, for example, Sourcetree custom actions.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Do-do-new
  • 794
  • 8
  • 15
0

Go to github.com or wherever it is, click branch, and rename it. Then run these locally:

git branch -m <old-branch-name> <new-branch-name>
git fetch origin
git branch -u origin/<new-branch-name> <new-branch-name>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Epirocks
  • 480
  • 4
  • 11
0

Updated solution for 2022

GitHub is now officially supporting its users in renaming branches and making the guidance available on GitHub Docs.

I have followed their steps and successfully renamed both of my local and remote branches.

In case the URL becomes broken, here are the solutions.

Rename remote branch

  1. On GitHub.com, navigate to the main page of the repository.
  2. Above the list of files, click Branches. enter image description here
  3. In the list of branches, to the right of the branch you want to rename, click on the edit symbol. enter image description here
  4. Type a new name for the branch and review information, then click Rename branch enter image description here

Updating a local clone after a branch name changes

As per GitHub Docs:

After you rename a branch in a repository on GitHub, any collaborator with a local clone of the repository will need to update the clone.

From the local clone of the repository on a computer, run the following commands to update the name of the default branch:

$ git branch -m OLD-BRANCH-NAME NEW-BRANCH-NAME
$ git fetch origin
$ git branch -u origin/NEW-BRANCH-NAME NEW-BRANCH-NAME
$ git remote set-head origin -a

Optionally, run the following command to remove tracking references to the old branch name:

$ git remote prune origin
Quan Bui
  • 175
  • 1
  • 13
-1

I believe the key is the realization that you are performing a double rename: master to master-old and also master-new to master.

From all the other answers I have synthesized this:

doublerename master-new master master-old

where we first have to define the doublerename Bash function:

# doublerename NEW CURRENT OLD
#   - arguments are branch names
#   - see COMMIT_MESSAGE below
#   - the result is pushed to origin, with upstream tracking info updated
doublerename() {
  local NEW=$1
  local CUR=$2
  local OLD=$3
  local COMMIT_MESSAGE="Double rename: $NEW -> $CUR -> $OLD.

This commit replaces the contents of '$CUR' with the contents of '$NEW'.
The old contents of '$CUR' now lives in '$OLD'.
The name '$NEW' will be deleted.

This way the public history of '$CUR' is not rewritten and clients do not have
to perform a Rebase Recovery.
"

  git branch --move $CUR $OLD
  git branch --move $NEW $CUR

  git checkout $CUR
  git merge -s ours $OLD -m $COMMIT_MESSAGE

  git push --set-upstream --atomic origin $OLD $CUR :$NEW
}

This is similar to a history-changing git rebase in that the branch contents is quite different, but it differs in that the clients can still safely fast-forward with git pull master.

Martin Vidner
  • 2,307
  • 16
  • 31
-5
git update-ref newref oldref
git update-ref -d oldref newref