Delete a branch on the remote (and clean up stale ones)
How do I delete a remote branch in Git?
Short answer
git push origin --delete <branch> removes it from the server. Deleting it locally with git branch -d doesn't touch the remote at all, and other people keep seeing stale copies until they run git fetch --prune.
git push origin --delete feature/old-work
Deletes the branch on the server; your local copy is untouched
Does this match your situation?
- A merged feature branch is still cluttering the branch list on GitHub.
- You deleted a branch locally but it's still on the remote.
- git branch -a shows remote branches that no longer exist.
Step-by-step fix
Delete it on the server
Both forms below do the same thing. The second is the older colon syntax, which reads as 'push nothing into that branch'.
step 1git push origin --delete feature/old-work # equivalent older syntax: git push origin :feature/old-workDelete your local copy too
Local and remote branches are independent. Lowercase -d refuses if the branch has unmerged commits, which is a useful guard; -D forces it.
step 2git branch -d feature/old-work # force, if it has unmerged work you're sure about: git branch -D feature/old-workClear out stale remote-tracking references
After anyone deletes a remote branch, every other clone keeps a stale origin/<branch> reference until it prunes. This is why git branch -a keeps listing branches that are long gone.
step 3git fetch --prune # make it automatic everywhere: git config --global fetch.prune trueClean up every merged branch at once
After a busy sprint, prune the locals that are fully merged into main. Always eyeball the list before piping it to a delete.
step 4git branch --merged main | grep -v -E '^\*|main|master' | xargs -n 1 git branch -dShow the PowerShell (Windows) version
PowerShell (Windows)git branch --merged main | Where-Object { $_ -notmatch '^\*|main|master' } | ForEach-Object { git branch -d $_.Trim() }
Why this works
Local branches, remote branches and remote-tracking branches are three separate things. `feature/x` is yours, `origin/feature/x` is your cached picture of the server, and the branch on the server is a third copy you only affect by pushing. Deleting any one of them leaves the others alone, which is why a branch can appear deleted for you and still be visible to everyone else — and why pruning is a distinct step.
If that didn’t work
- Deleted the wrong branch? The commits survive — find the hash with git reflog or on the pull request page and recreate it.
- 'remote ref does not exist' means it was already deleted; run git fetch --prune to refresh your view.
- A protected branch will refuse deletion until you change the rule in the host's settings.
How to stop it happening again
- Turn on your host's 'automatically delete head branches after merge' setting.
- Set fetch.prune true globally so stale references never accumulate.
- Run git branch --merged main periodically to see what's safe to remove.
Commands used in this guide
Still stuck?
Search the full command reference and every other rescue guide — there are 56 of them, covering everything from detached HEAD to force-push disasters.
Browse all guides →Frequently asked questions
How do I delete a remote branch in Git?
git push origin --delete <branch-name>, or the older git push origin :<branch-name>. Both remove the branch from the server. Your local branch and everyone else's cached copy are separate and need their own cleanup.
Why does git branch -a still show a branch I deleted from the remote?
That's a stale remote-tracking reference — a local cache of what the server looked like when you last fetched. Run git fetch --prune to remove references to branches that no longer exist upstream.
Can I recover a remote branch I deleted?
Usually. The commits aren't destroyed, so if you or a colleague still has them locally you can just push the branch back up. On GitHub, a closed pull request for that branch offers a Restore branch button.
Related rescue guides
I deleted a Git branch — how do I get it back?
Deleting a branch removes a pointer, not the commits. Find the branch's last commit hash in the reflog and recreate the branch at that hash with git branch <name> <hash>. If the branch was pushed, the copy on the server may still exist and can simply be fetched back.
Read the fix →Always fixableHow do I rename a Git branch?
git branch -m <new-name> renames the branch you're on. Renaming on the server takes two more steps, because Git has no rename operation for remote branches — you push the new name and delete the old one.
Read the fix →Always fixableHow do I change the remote URL of a Git repository?
git remote set-url origin <new-url> repoints an existing remote. It's a purely local change — nothing on either server is touched — so it's the safe way to switch between HTTPS and SSH, move to a new host, or fix a URL after renaming the repository.
Read the fix →Always fixableHow do I sync my fork with the upstream repository?
Add the original repository as a remote called upstream, fetch it, then merge or rebase upstream/main into your main and push. GitHub's 'Sync fork' button does the same thing, but doing it locally gives you control when your fork has diverged.
Read the fix →