keepcalculator

06 Numbers and Powers

Git Branch Cleanup: Check Merged Work Before Deleting?

Card No. 06·32268 · Updated · Standard formula, shown below

Yes, always check whether a branch has been merged before deleting it, because deleting an unmerged branch permanently discards its commits and any work that exists only on that branch. You can verify merge status with git branch --merged and git branch --no-merged, then delete safely with git branch -d (which refuses to delete unmerged branches) or force-delete with -D only when you are certain the work is no longer needed.

Why Checking Matters

Git branches are lightweight pointers to commits. Deleting a branch does not immediately erase the commits, but it removes the only easy reference to them. If those commits are not reachable from another branch or tag, they become “dangling” and are eventually garbage-collected, making recovery difficult and often impossible for casual users. The risk is highest with local branches that were never pushed, since no remote copy exists. A quick check prevents losing hours of work that you might have forgotten about.

How Git Tracks Merge Status

Git determines whether a branch is merged by checking if its tip commit is an ancestor of another branch (usually your current branch or main). If every commit on the branch is already reachable from the target branch, Git considers it merged. This works for both regular merges and fast-forward merges. However, a squash merge (common on GitHub) does not create a merge commit, so Git may not recognize the branch as merged even though the changes were applied. In that case, git branch --merged will not list the branch, and you must verify manually.

Commands to Check Before Deleting

Run these commands from your terminal inside the repository:

  • git branch --merged main — lists branches whose tip is reachable from main. These are safe to delete with -d.
  • git branch --no-merged main — lists branches that contain commits not in main. Deleting these requires -D.
  • git branch -vv — shows each branch’s upstream tracking branch and last commit, helping you spot stale or unpushed branches.
  • git log --oneline main..branch-name — shows commits in branch-name that are not in main. If this list is empty, the branch is fully merged.

Safe Deletion Workflow

Follow these steps to clean up without risking work:

  1. Switch to your main branch: git checkout main (or git switch main).
  2. Fetch the latest remote state: git fetch --prune to remove stale remote-tracking branches.
  3. Run git branch --merged to see which branches are safe. Review the list carefully.
  4. Delete each safe branch with git branch -d branch-name. Git will refuse if the branch is not fully merged.
  5. For branches in the --no-merged list, investigate before using -D. Check if the work was squash-merged or if you have a backup.
  6. Delete remote branches with git push origin --delete branch-name only after confirming the local branch is merged or no longer needed.

Common Pitfalls and Misconceptions

A frequent mistake is assuming that because a pull request was closed, the branch is merged. Pull requests can be closed without merging, or merged via squash, which Git does not detect as a merge. Another misconception is that git branch -d is dangerous — it is actually the safe option because it refuses to delete unmerged branches. The dangerous command is -D, which bypasses the safety check. Also, deleting a branch does not delete the remote branch; you must do that separately. Finally, branches that were merged into a feature branch but not into main will still show as unmerged relative to main, so always check against the branch where the work should have landed.

Recovering a Deleted Branch

If you accidentally delete a branch, you might still recover it using the reflog. Run git reflog to see recent HEAD movements, find the commit hash of the branch’s tip, then recreate the branch with git branch branch-name commit-hash. This works only if the commits have not been garbage-collected, which typically happens after 30 days (or sooner with aggressive pruning). If the branch was pushed to a remote, you can also recreate it from the remote-tracking branch, e.g., git branch branch-name origin/branch-name, even after the remote branch is deleted, as long as the remote-tracking ref still exists locally. After a git fetch --prune, that ref may disappear, so act quickly.

Automating Cleanup

For repositories with many branches, manual checking is tedious. You can list all local branches merged into the current branch and delete them in one command: git branch --merged | grep -v "\*" | xargs -n 1 git branch -d. This skips the current branch (marked with *) and deletes only merged ones. Be cautious: this uses the current branch as the reference, so switch to main first. For remote branches, similar scripts exist, but always review the list before running bulk deletions. Some teams use Git hooks or CI scripts to automatically delete remote branches after a pull request is merged, but local branches remain the developer’s responsibility.

Frequently Asked Questions

What is the difference between git branch -d and -D?

-d is the safe delete: it refuses to delete a branch that has unmerged commits, protecting you from accidental loss. -D forces deletion regardless of merge status, which is useful when you are certain the work is obsolete or already saved elsewhere. Always try -d first; use -D only after verifying the branch is truly expendable.

How do I check if a branch was squash-merged?

Git cannot detect squash merges automatically because the commits are squashed into a single new commit on the target branch. To check, compare the diff: git diff main...branch-name shows what would change if you merged the branch. If the output is empty, the changes are already present in main, so the branch is effectively merged even though git branch --merged does not list it. You can then safely delete with -D.

Will deleting a branch delete its commits?

No, deleting a branch only removes the pointer to the branch tip. The commits remain in the object database until they become unreachable and are garbage-collected (usually after 30 days). If you realize you need the work, you can recover it via git reflog or by recreating the branch from the commit hash. However, if you also run git gc --prune=now, the commits may be permanently removed.

Should I delete remote branches too?

Yes, if you are cleaning up a feature branch that has been merged, deleting the remote branch keeps the repository tidy. Use git push origin --delete branch-name. This does not affect your local branch. Many teams delete remote branches automatically after a pull request is merged, but if you manage them manually, make sure the remote branch is merged before deleting, otherwise you lose the remote copy that might be the only backup.

Why does git branch --merged show branches I thought were unmerged?

This happens when the branch was fast-forwarded into the target branch, meaning the target branch now contains all the commits from the feature branch. Fast-forward merges do not create a merge commit, but Git still sees the branch tip as an ancestor, so it lists it as merged. This is correct behavior — the branch’s commits are already in the target, so deleting it is safe.

Can I delete the branch I am currently on?

No, Git will refuse with an error: “Cannot delete branch ‘X’ checked out at…” You must switch to another branch first, typically main. This is a safety feature to prevent you from losing your working directory’s context. After switching, you can delete the branch normally.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →