Feature, bug-fix, hotfix, and experiment branches are useful while work is in progress, but old branches can clutter a repository after they are merged or abandoned. Git stores local branches and remote branches separately, so removing one does not automatically remove the other. This guide shows how to review and clean up both safely.
Local branches and remote-tracking branches
A local branch, such as feature/login, is a reference in your local repository. A remote-tracking branch, such as origin/feature/login, is your local record of a branch on a remote named origin. It is updated when you fetch. The branch on the server is a separate reference managed by that remote.
List branches before choosing one to remove:
git branch
git branch -r
git branch -a
git branch lists local branches, git branch -r lists remote-tracking branches, and git branch -a lists both. The asterisk marks the currently checked-out local branch.
Review merge status first
Check your current branch and working tree, then inspect recent history and branches already merged into your target branch:
git status
git branch --merged main
git log --oneline --decorate --graph -10
Replace main with the branch that received the work, such as develop. Git's merged-branch check depends on the branch you specify (or, without one, the current branch); review the output rather than deleting every listed name automatically. Confirm pull requests are complete, tests have passed, and teammates no longer need the branch.
Delete a merged local branch
Switch away from the branch before deleting it. Then use lowercase -d, which refuses to delete a branch Git considers unmerged into its upstream or the current branch:
git switch main
git branch -d feature/login
If Git reports that the branch is not fully merged, stop and inspect its commits. The branch may contain work that has not reached the target branch. A branch checked out in another linked worktree also cannot be deleted until you switch that worktree to a different branch or remove the worktree deliberately.
Force-delete a local branch only when intentional
Uppercase -D forces branch deletion even if Git cannot confirm that its commits are merged:
git branch -D experiment/old-parser
Caution: force-deleting removes the branch name that points to the work. If the commits are not reachable from another ref, they may later become difficult to recover. Inspect the branch first, for example with git log main..experiment/old-parser, and keep or back up any work you may need.
Delete a branch from a remote
After confirming a branch is merged and no longer needed by the team, delete it from the server with the explicit modern syntax:
git push origin --delete feature/login
Replace origin with the correct remote name. This removes the remote branch; it does not delete your local feature/login branch or automatically remove your teammates' local copies. Coordinate with collaborators and check that any associated pull request or deployment workflow is complete first.
Prune stale remote-tracking references
After a remote branch is deleted, your repository may still list its old tracking reference until you fetch and prune:
git fetch --prune
To prune references for one remote specifically:
git remote prune origin
Pruning removes stale remote-tracking references from your local repository; it does not delete active branches from the server. You can also configure pruning for future fetches with git config fetch.prune true, if that behavior suits your workflow.
A safe cleanup workflow
- Run
git statusand switch to a stable branch such asmain. - Confirm the feature branch has been merged into the intended target and is no longer in use.
- Delete the local branch with
git branch -d branch-name. - Delete the remote branch with
git push origin --delete branch-namewhen team policy allows. - Run
git fetch --pruneto remove stale tracking references. - Verify with
git branchandgit branch -r.
Common mistakes
- Using
-Dbefore checking merge status: try-dfirst and investigate Git's warning. - Deleting the branch you are using: switch to another branch first; check other linked worktrees if Git still refuses.
- Assuming local deletion removes the remote: delete each reference in the place where it exists.
- Removing a shared branch too early: verify merged code, open reviews, deployments, and teammate dependencies before deleting it remotely.
- Confusing pruning with server deletion: pruning only removes stale local tracking references for branches already gone from the remote.
Quick reference: use git branch -d branch-name for a merged local branch, git push origin --delete branch-name for a remote branch, and git fetch --prune to clean up stale remote-tracking references. Reserve git branch -D for work you have verified you can discard.