How to Recover a Branch You Accidentally Deleted
by Eric Hanson, Backend Developer at Clean Systems Consulting
The Commits Are Still There
You ran git branch -D feature/payment-retry and immediately realized you hadn't merged it. Or your Git host auto-deleted the branch after merge, but the merge was to the wrong target. Or you ran git push origin --delete feature/payment-retry and regretted it immediately.
The branch is gone. The commits are not. In Git's object model, a branch is just a named pointer to a commit. Deleting the branch removes the pointer, not the commits themselves. Those commits remain in the object store until Git's garbage collector runs — typically not for at least two weeks, and not at all if the objects are reachable from any other reference (tags, stash, reflog).
The recovery path depends on whether you're recovering a local branch, a remote branch, or both.
Recovering a Local Branch
Reflog is your first stop. Reflog records every movement of HEAD and every branch pointer, including the tip commit of a branch just before it was deleted.
# Show recent HEAD movements
git reflog
# Output example:
# a3f9d24 HEAD@{0}: checkout: moving from feature/payment-retry to main
# b7c12e1 HEAD@{1}: commit: Add exponential backoff to retry logic
# f4d8a09 HEAD@{2}: commit: Add PaymentRetryService
# 9e1b3c7 HEAD@{3}: checkout: moving from main to feature/payment-retry
The entry HEAD@{0} shows you switched from feature/payment-retry to main. The entry at HEAD@{1} is the last commit on the deleted branch — SHA b7c12e1.
Recreate the branch at that commit:
git checkout -b feature/payment-retry b7c12e1
# or
git branch feature/payment-retry b7c12e1
If you know the branch name but not the SHA, search reflog specifically:
git reflog | grep 'feature/payment-retry'
# Shows all reflog entries mentioning that branch name
You can also search for the branch's last known tip using the branch-specific reflog (which may still exist briefly after deletion):
git reflog show feature/payment-retry
# If it still exists in reflog, this shows commits from that branch's perspective
Recovering a Remote Branch
If the branch was deleted on the remote (GitHub, GitLab, etc.), your recovery options depend on timing and who has local copies.
If you still have the branch locally (you deleted it remotely but not locally):
# Re-push it
git push origin feature/payment-retry
If another developer has it locally:
# Have them push it back
git push origin feature/payment-retry
If nobody has it locally and it was deleted recently from GitHub:
GitHub retains deleted branches for a period and exposes a "Restore branch" option in the PR associated with the branch. Navigate to the closed or merged PR → look for "feature/payment-retry was deleted" → click "Restore branch." This works if there was an associated PR. If the branch was pushed but never had a PR, this option doesn't exist.
GitLab has a similar restore option in the repository's branch management UI for recently deleted branches.
If the remote branch is gone and nobody has it locally:
This is the worst case. Your only hope is the object store on the remote server, which you likely don't have direct access to. However, if you have any local repository that ever fetched from the remote while that branch existed, your local object store may contain the commits even without a local branch pointing to them.
# Check if any objects related to your lost work exist locally
git fsck --lost-found
# Creates .git/lost-found/commit/ with dangling commit objects
ls .git/lost-found/commit/
# Each file is a commit SHA — read them to find your work
git log --oneline <sha>
git show <sha>
Walk through the dangling commits until you find the one that's the tip of your lost branch. Then recreate the branch pointing to it.
If You Had Uncommitted Changes When You Deleted
This is the harder case. Git stash is reflogged, so if you stashed before deleting:
git stash list
git stash show -p stash@{0} # inspect the stash
git stash pop # restore it
But if you had uncommitted, unstaged changes that weren't stashed when you deleted the branch — those are truly gone. Git's object store only tracks committed content. The working tree's state is not preserved unless it was committed or stashed.
This is the one scenario in Git that is genuinely difficult to recover from. The lesson: if you're about to do anything destructive (branch deletion, reset --hard, rebase), run git stash push -m "safety: $(date)" first.
Preventing Accidental Deletion
For local branches:
# -d (lowercase) only deletes if the branch is fully merged
# -D (uppercase) force-deletes regardless
git branch -d feature/payment-retry # safe: fails if not merged
git branch -D feature/payment-retry # dangerous: always deletes
Make -D a deliberate choice, not a habit.
For remote branches on GitHub, enable branch protection on main to prevent accidental deletion of the main branch. For other branches, consider requiring PRs before deletion for long-lived branches (release branches, develop branches).
The GitHub CLI gh makes it easy to check before deleting:
gh pr list --head feature/payment-retry
# Verify there's a merged PR before deleting
git push origin --delete feature/payment-retry
Recovery is almost always possible. The window is wide — reflog entries persist for 90 days by default (gc.reflogExpire). Don't panic, open reflog, and find the SHA.