Short answer: git branch -m old-name new-name renames a local branch, and on the branch you have checked out git branch -m new-name is enough. A branch on the remote cannot be renamed in place: push it under the new name with git push -u origin new-name, then delete the old name with git push origin --delete old-name. Everyone else who has a clone then fetches with --prune and points their local branch at the new name.
git branch -m feature/login-form feature/login # local rename
git push -u origin feature/login # publish the new name, track it
git push origin --delete feature/login-form # remove the old name on the remoteEvery command and every output block below comes from Git 2.39.5, the version Debian 12 ships, run in a throwaway repository with a bare repository beside it as the remote. That is why the push lines read To ../app.git; yours show your Git host’s address.
Cheat sheet: renaming a branch
| Task | Command |
|---|---|
| Rename the branch you are on | git branch -m new-name |
| Rename any other local branch | git branch -m old-name new-name |
| Rename and overwrite an existing branch | git branch -M old-name new-name |
| Copy instead of rename (keeps the old one) | git branch -c old-name new-name |
| Push the new name and track it | git push -u origin new-name |
| Delete the old name on the remote | git push origin --delete old-name |
| Both remote steps in one push | git push -u origin new-name :old-name |
| Another clone: drop deleted remote branches | git fetch --prune |
| Another clone: track the new name | git branch -u origin/new-name new-name |
| Refresh origin/HEAD after a default branch change | git remote set-head origin -a |
| Check a name before using it | git check-ref-format --branch "new-name" |
| Name new repositories main from the start | git config --global init.defaultBranch main |
Rename a local branch with git branch -m
-m stands for move. With two names it renames the first branch to the second, whether or not it is checked out. With one name it renames the branch you are on. Nothing about the commits changes: the branch is a pointer, and only the pointer gets a new name. Git also moves the branch’s reflog and its settings along, including the upstream it tracks, and that is the part that catches people:
git branch -m feature/login-form feature/login
git branch -vv* feature/login a937de3 [origin/feature/login-form] Add login form
main ef64f71 [origin/main] Initial commitThe local branch is now feature/login, but it still tracks origin/feature/login-form. A plain git push refuses to push between two different names under the default push.default=simple:
fatal: The upstream branch of your current branch does not match
the name of your current branch. To push to the upstream branch
on the remote, use
git push origin HEAD:feature/login-form
To push to the branch of the same name on the remote, use
git push origin HEADIf the branch was never pushed, you are done after git branch -m. If it was, carry on with the remote below. Git also accepts git branch -m on a brand new repository before the first commit, which is the hint git init prints when it creates master: git branch -m main right after git init just changes the name the first commit will land on.
Rename the branch on the remote
A push can create and delete branch names on a remote, but it has no rename operation. Renaming on the remote is therefore two pushes: one that creates the new name from your local branch and one that deletes the old name.
- 1Push the new name and set it as upstream
any system git push -u origin feature/loginExample output To ../app.git * [new branch] feature/login -> feature/login branch 'feature/login' set up to track 'origin/feature/login'.-u(long form--set-upstream) replaces the stale tracking entry, so plaingit pushandgit pullwork again. - 2Delete the old name on the remote
any system git push origin --delete feature/login-formExample output To ../app.git - [deleted] feature/login-formThe older spelling
git push origin :feature/login-form(an empty source before the colon) does the same. Both steps fit into one push:git push -u origin feature/login :feature/login-form. - 3Check the result
any system git branch -vv git branch -aExample output of git branch -vv * feature/login a937de3 [origin/feature/login] Add login form main ef64f71 [origin/main] Initial commit
Update other clones after a rename
Every other clone, a teammate’s laptop or the checkout on your server, still has a local branch with the old name that tracks a remote branch that no longer exists. A normal fetch keeps the stale origin/old-name around; --prune removes it and shows what happened:
git fetch --prune
git branch -vvFrom ../app
- [deleted] (none) -> origin/master
(refs/remotes/origin/HEAD has become dangling)
* [new branch] main -> origin/main
* master 95da554 [origin/master: gone] Initial commitgone means the upstream was deleted. A git pull at this point fails with Your configuration specifies to merge with the ref 'refs/heads/master' from the remote, but no such ref was fetched. Three commands bring the clone in line:
git branch -m master main
git branch -u origin/main main
git remote set-head origin -abranch 'main' set up to track 'origin/main'.
origin/HEAD set to mainThe last line only matters when the default branch changed: it updates origin/HEAD, the clone’s note of which branch the remote treats as the default. The has become dangling line in the fetch output above means that note still pointed at the deleted branch, and this command repairs it. To make every fetch prune, set git config --global fetch.prune true once.
Rename master to main
Renaming the default branch is the same procedure with one extra step in the middle, and the order matters: the remote refuses to delete the branch it uses as its default. This is what deleting master before switching the default looks like on a bare repository; hosted remotes refuse in a similar way:
remote: error: refusing to delete the current branch: refs/heads/master
To ../app.git
! [remote rejected] master (deletion of the current branch prohibited)
error: failed to push some refs to '../app.git'- 1Rename locally and push main
any system git switch master git pull git branch -m master main git push -u origin main - 2Make main the default branch on the remote
On a hosted remote, change the default branch in your Git host’s repository settings. On a bare repository you host yourself, the default is whatever its
HEADpoints at; check it from your clone and change it on the server:any system · check from the clone git ls-remote --symref origin HEADExample output ref: refs/heads/master HEAD 95da5545b8e1b113e6a8ac91e8ab839e33e04499 HEADon the server · inside the bare repository git symbolic-ref HEAD refs/heads/main - 3Delete master on the remote
any system git push origin --delete master git remote set-head origin -a - 4Update every reference to the old name
CI pipelines, deploy scripts, server-side hooks and documentation often name the branch. A recursive grep finds them:
grep -rn --exclude-dir=.git 'master' .. Then each clone runs the three commands from the previous section.
For repositories you create from now on, set the initial name once and git init uses it, without the hint it otherwise prints about master:
git config --global init.defaultBranch maingit branch -M: rename even if the name exists
-M is short for --move --force. Where -m stops with fatal: a branch named 'main' already exists, -M goes ahead and replaces the existing branch with the one you rename.
-M also refuses to overwrite the branch you are on: fatal: cannot force update the branch 'master' checked out at '…'. Switch to another branch first.
Common errors and what they mean
| Message | Cause | Fix |
|---|---|---|
fatal: a branch named 'X' already exists | The new name is taken | Pick another name, or delete the other branch first; -M only if you mean to discard it |
fatal: No branch named 'X'. | Typo, or the branch exists only on the remote | git branch -a; for a remote-only branch, git switch X creates the local one first |
fatal: 'X' is not a valid branch name | Spaces, two dots, a leading dash, a name ending in .lock and similar | Test names with git check-ref-format --branch |
The upstream branch of your current branch does not match the name of your current branch | Renamed locally, still tracking the old remote name | git push -u origin new-name |
(deletion of the current branch prohibited) | Deleting the remote's default branch | Change the default branch first |
Your configuration specifies to merge with the ref 'refs/heads/X' | Another clone, after the rename | git fetch --prune, then git branch -u origin/new-name |
[origin/X: gone] | The upstream was deleted on the remote | git branch -u origin/new-name, or git branch --unset-upstream |
Changing only the case of a name
On Linux, git branch -m Main main works like any other rename (it did on the Debian 12 test box). macOS and Windows file systems ignore case by default, and Git can store branch names as files there, so a case-only rename may be refused as already exists. Go through a temporary name instead of reaching for -M: git branch -m Main tmp-rename, then git branch -m tmp-rename main.
On a server: deploy checkouts and self-hosted remotes
A rename reaches a server in two places. A checkout that deploys with git pull is just another clone: after the remote rename its next pull stops with the merge with the ref error above, and the deploy quietly keeps serving the old code. Run the three commands from updating other clones in that checkout, as the user that owns it, and update any script or timer that names the branch.
If the remote is a bare repository on your own server, for example one you push to over SSH, set its HEAD with git symbolic-ref as in step 2 above, and read its hooks/post-receive: a hook that checks out refs/heads/master into the web root ignores pushes to main without a word. Pushing over SSH to a server you run needs a key, set up as in generating an SSH key, and an entry in your SSH config file saves typing the port and user each time. A Linux VPS with root access is enough to host bare repositories like this for a small team. If git itself is missing on a fresh server, see git: command not found.
Frequently asked
How do I rename a Git branch?
Run git branch -m old-name new-name, or git branch -m new-name to rename the branch you are on. That renames it locally only. If the branch was already pushed, also run git push -u origin new-name and git push origin --delete old-name.
How do I rename a branch on the remote?
A remote branch cannot be renamed in place. Push your local branch under the new name with git push -u origin new-name, then delete the old name with git push origin --delete old-name. Every other clone then runs git fetch --prune, renames its local branch and points it at the new one with git branch -u origin/new-name.
How do I rename master to main?
Run git branch -m master main and git push -u origin main, then make main the default branch in your Git host's settings, or with git symbolic-ref HEAD refs/heads/main inside a bare repository you host yourself. Only then delete master with git push origin --delete master: the remote refuses to delete its default branch.
What is the difference between git branch -m and git branch -M?
-m refuses to rename a branch onto a name that already exists. -M is move with force: it replaces the existing branch with the renamed one, and the replaced branch's commits are then only reachable through the remote, another branch or the reflog. Use -M only when you mean to throw the target branch away.