Delete Git branches that have already been merged

List branches relative to an explicit integration target, review candidates before deletion, and distinguish ancestry checks from squash-merge completion.

Best practices
Illustration of Git branches and version history

Use git branch --merged TARGET to list local branches whose tips are reachable from a chosen integration target. Review that list before deleting branches, especially long-lived release branches or branches checked out in another worktree.

Refresh and select the target

git fetch origin
git switch main
git merge --ff-only origin/main
git branch --merged main

The fast-forward-only update refuses divergence instead of silently creating a merge. If it fails, inspect the history before continuing. You can also compare against origin/main directly without moving local main.

--merged with no target uses HEAD. A branch merged only into develop may not be reachable from main. Squash merges and rebased integrations can leave the original branch tip unreachable even when equivalent changes were integrated; the ancestry test does not prove or disprove semantic equivalence.

Delete reviewed local candidates

For a small set, explicit names are easiest to inspect:

git branch -d -- feature/old-1 feature/old-2

For a POSIX-shell batch workflow, first generate and edit a candidate file outside the repository:

git for-each-ref --merged=main --format='%(refname:short)' refs/heads/

Exclude main, master, develop, release branches you retain, and any other protected names. Then, with only approved branch names in branches-to-delete.txt:

while IFS= read -r branch; do
  [ -z "$branch" ] && continue
  git branch -d -- "$branch" || break
done < branches-to-delete.txt

-d checks whether a branch is fully merged into its configured upstream, or into HEAD if it has no upstream. Therefore, -d alone is not a guarantee that it was merged into your intended target; the explicit candidate check matters. Git also refuses to delete a branch checked out in a worktree. Do not automatically escalate a refusal to -D.

Delete a remote branch separately

git fetch --prune origin
git branch -r --merged origin/main
# After reviewing a specific candidate:
git push origin --delete feature/old-1

Remote-tracking refs are local observations. Pruning removes stale ones; it does not delete server branches. The actual push deletes the named server branch and requires authorization. If the remote tip may have changed since review, refresh and recheck it or use an explicit expected-tip lease.

Hosting platforms may offer automatic deletion after merging a pull request. Apply that policy only to branches that fit the team's retention rules.

Does deleting the branch delete its commits?

It removes a ref, not every referenced object immediately. Commits still reachable from the integration target remain in its history. Unreachable commits may eventually be pruned, so preserve a ref for anything you still need.

See git-branch and git-fetch.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting