Fix 'error: The branch is not fully merged' When Deleting a Git Branch

beginner๐Ÿ“ฆ Git2026-06-27| Git 2.x on Linux, macOS, Windows (Git Bash / WSL)

Error Message

error: The branch 'feature/my-feature' is not fully merged. If you are sure you want to delete it, run 'git branch -D feature/my-feature'.
#git#branch#merge#delete

What just happened

You ran git branch -d feature/my-feature to clean up after a finished task, and Git refused:

error: The branch 'feature/my-feature' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/my-feature'.

Those commits on feature/my-feature aren't reachable from your current branch โ€” usually main or develop. Delete now and Git will eventually garbage-collect them. Work gone.

Eventually is the key word. The commits still exist right now. You have time to investigate before anything bad happens.

Why Git blocks the deletion

git branch -d (lowercase) is the safe variant. It checks whether every commit on the branch is already reachable from its upstream or from HEAD. Find one that isn't, and it refuses.

Four situations trigger this:

  • The branch was merged via a squash merge or rebase โ€” the original commit SHAs don't exist on main, only a new squashed or rebased version does.
  • The branch was merged into a different branch than the one you're currently on.
  • The pull request was closed without merging and you're about to lose actual work.
  • Someone merged it remotely and you haven't fetched yet.

Step 1 โ€” Figure out what's actually unmerged

Before reaching for -D, spend 30 seconds on this:

# Commits on the feature branch that are NOT on main
git log main..feature/my-feature --oneline

No output means the branch is effectively empty relative to main โ€” safe to force-delete. If you do see commits, read the messages. Do they look like work you've already seen land on main under a different hash?

# Cross-reference: what's landed on main lately?
git log --oneline main | head -20

Also worth checking whether the remote already cleaned this up after a merged PR:

git fetch --prune
git branch -r

Scenario A โ€” Branch was merged via squash or rebase (most common)

Nine times out of ten, this is the culprit. GitHub's default "Squash and merge" button and GitLab's "Squash commits" option both rewrite commit history โ€” the PR lands on main as a single new commit with a brand-new SHA, so Git doesn't recognize the original branch commits as merged.

Quick sanity check:

# Should be empty if the work is already on main
git diff main...feature/my-feature

Empty diff? The code is safely on main. Force-delete the local branch:

git branch -D feature/my-feature

Scenario B โ€” Branch is merged into a different base branch

The feature might have landed in develop while you're standing on main. Check against the right branch:

git log develop..feature/my-feature --oneline

Empty? Switch to that branch and use the safe delete:

git checkout develop
git branch -d feature/my-feature

Or skip the checkout once you've confirmed the work is there:

git branch -D feature/my-feature

Scenario C โ€” The work is genuinely unmerged

If git log main..feature/my-feature --oneline shows commits you've never seen on main, stop. Don't delete yet. You have three options:

Option 1 โ€” Merge it now:

git checkout main
git merge feature/my-feature
git branch -d feature/my-feature

Option 2 โ€” Cherry-pick just the commits you need:

# Grab the hash from git log output
git cherry-pick <commit-hash>

Option 3 โ€” Tag it before deleting (safety net):

git tag backup/feature-my-feature feature/my-feature
git branch -D feature/my-feature

The tag keeps the commit reachable indefinitely. To recover later: git checkout -b feature/my-feature backup/feature-my-feature.

The nuclear option โ€” and when it's actually fine

git branch -D feature/my-feature

Uppercase -D skips the merge check entirely. Use it when:

  • You ran git diff main...feature/my-feature and got nothing unique back.
  • The PR was squash-merged or rebase-merged and you're just cleaning up stale local refs.
  • It was a throwaway experiment you deliberately want to discard.

Don't use it blindly. This error is Git asking you to think for two seconds before nuking work you might need.

Clean up remote tracking references too

Deleting the local branch leaves the remote-tracking reference behind. Clean it up:

# Delete the remote branch if it still exists on the server
git push origin --delete feature/my-feature

# Or prune stale remote references after the server already deleted it
git fetch --prune

Verify the fix

# Branch should be gone locally
git branch | grep feature/my-feature
# (no output = good)

# Confirm commits are on main
git log main --oneline | head -10

# Check for dangling remote refs
git remote prune origin --dry-run

Quick reference

# Diagnose
git log main..feature/my-feature --oneline   # what's not on main?
git diff main...feature/my-feature            # any content difference?

# Safe delete (after verification)
git branch -D feature/my-feature

# Safety net before deleting unmerged work
git tag backup/feature-my-feature feature/my-feature
git branch -D feature/my-feature

Related Error Notes