Deleting Branches
Branches are cheap, but they pile up. Deleting old branches keeps the list manageable and prevents confusion (“is this branch alive or dead?”). Deletion in Git is safe by default — it refuses to delete branches whose commits aren’t already merged somewhere, so you cannot easily lose work.
Delete a merged branch (safe)
git branch -d feature-x # Deleted branch feature-x (was 1f9ab2c).
-d (lowercase) only works if the branch’s tip is already reachable from another branch — usually because it has been merged. If not, Git refuses:
The safety check
error: The branch 'feature-x' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature-x'.
Force-delete an unmerged branch
-D (capital) bypasses the safety check
git branch -D feature-x # Deleted branch feature-x (was 1f9ab2c).
Cannot delete the branch you are on
git branch -d main # error: Cannot delete branch 'main' checked out at '/Users/you/my-repo' # Switch away first git switch other-branch git branch -d main
Delete a remote branch
Delete on the server
git push origin --delete feature-x # - [deleted] feature-x # Short form git push origin :feature-x
The empty source (:branch) form is older but still works everywhere. Newer Git users prefer the explicit --delete.
Remove stale local pointers to deleted remote branches
After a teammate deletes a remote branch
git fetch --prune # - [deleted] (none) -> origin/feature-x # Or auto-prune on every fetch git config --global fetch.prune true
Bulk-delete merged branches
Clean up all merged branches except main
# Show what would be deleted git branch --merged | grep -vE '(^\*|main|master|develop)' # Actually delete them git branch --merged | grep -vE '(^\*|main|master|develop)' | xargs git branch -d
Save it as an alias for easy cleanup:
git config --global alias.cleanup "!git branch --merged | grep -vE '(^\\*|main|master|develop)' | xargs -n 1 git branch -d" # Then: git cleanup
Delete every remote branch matching a pattern
Use with care
# List first
git branch -r | grep 'feature/'
# Delete
git branch -r | grep 'feature/' | sed 's|origin/||' | xargs -I {} git push origin --delete {}Recovering a deleted branch
Even after deletion, commits hang around in the reflog and the object database for ~90 days. Recovery is usually possible.
Resurrect a branch
# Find its last hash in the reflog
git reflog | grep deleted-branch
# 1f9ab2c HEAD@{42}: branch: Created from ...
# Recreate the branch at that commit
git switch -c deleted-branch 1f9ab2cWhat -d vs -D actually do
git branch -d— refuses unless the branch is merged into the upstream OR into the current branch. Safest option.git branch -D— deletes unconditionally. Same asgit branch --delete --force.Neither command deletes commits — they delete the pointer. The commits are GC’d later when nothing references them.
Workflow recap
The clean post-merge cycle
# After your PR is merged on GitHub: git switch main git pull --prune # bring in the merge, prune stale refs git branch -d feature-x # delete locally # 'git push origin --delete' if you didn't tick "delete after merge" on GitHub
git switch main && git pull --prune && git branch -d <branch>. Two weeks of this and your branch list stays sane forever.