Recovering a Deleted Branch
You deleted a branch and then realised it still had work you needed. Do not panic — Git almost never truly deletes commit data. The commits still exist as "dangling" objects in the repository. The key tool for recovering them is git reflog, which records every position HEAD has been at, even for branches that no longer exist.
Why recovery is usually possible
When you delete a branch with git branch -d or git branch -D, Git only removes the pointer (the label that says "branch-name = this commit hash"). The actual commit objects remain in the repository until Git's garbage collector removes them. The default reflog expiry is 90 days, giving you a generous window to recover.
Step 1: Find the lost commit using reflog
View the reflog
git reflog
# Output (most recent first):
# abc1234 HEAD@{0}: checkout: moving from feature-payments to main
# bcd2345 HEAD@{1}: commit: Add Stripe webhook handler
# cde3456 HEAD@{2}: commit: Add payment model
# def4567 HEAD@{3}: checkout: moving from main to feature-payments
# ghi5678 HEAD@{4}: commit: Update READMEFilter reflog by branch name if the list is long
git reflog show --all | grep feature-payments
# bcd2345 refs/heads/feature-payments@{0}: commit: Add Stripe webhook handler
# cde3456 refs/heads/feature-payments@{1}: commit: Add payment modelStep 2: Inspect the commit to confirm it is the right one
Look at what is in the commit
git show bcd2345 # commit bcd2345... # Author: Jane Dev <jane@example.com> # Date: Mon Jan 13 15:30:00 2025 +0000 # # Add Stripe webhook handler # # diff --git a/src/payments/webhook.js b/src/payments/webhook.js # ...
Step 3: Re-create the branch
Create a new branch pointing at the recovered commit
git branch recovered-feature-payments bcd2345 # Branch 'recovered-feature-payments' set up to track nothing. # Verify it is there with the right history git log recovered-feature-payments --oneline -5 # bcd2345 Add Stripe webhook handler # cde3456 Add payment model # def4567 ... (from main)
Alternative: checkout directly using reflog syntax
# This creates the branch and switches to it in one step
git checkout -b recovered-feature-payments HEAD@{1}
# Switched to a new branch 'recovered-feature-payments'If the branch was also on a remote
If the branch was pushed to the remote before it was deleted locally, you may be able to fetch it directly from the remote — even if the remote-tracking branch reference was also removed.
Try fetching the deleted branch from remote
# If the branch still exists on the remote: git fetch origin feature-payments git switch feature-payments # Already up to date. # If the remote reference is gone, check with: git ls-remote origin | grep feature-payments # If nothing returns, the remote branch is also gone # Ask a teammate if they have it locally # git fetch <their-remote> feature-payments
Recovering when you cannot find the hash in reflog
If the branch was very old, or if git gc ran recently, the reflog entry may be gone. You can still search for dangling commits:
Find all dangling commits
git fsck --lost-found # dangling commit bcd2345abc1234... # dangling commit ... # (listed in no particular order) # Then inspect each dangling commit: git show bcd2345abc1234 # Once found: git branch recovered-branch bcd2345abc1234
The reflog expiry window
Default expiry for reachable objects: 90 days (
gc.reflogExpire).Default expiry for unreachable objects: 30 days (
gc.reflogExpireUnreachable).Check your config:
git config gc.reflogExpire.You can extend expiry:
git config --global gc.reflogExpire "365 days".After
git gc --prune=now, dangling commits are deleted permanently.
Complete recovery walkthrough
Run
git reflogto see all HEAD movements.Identify the hash of the last commit on the deleted branch.
Run
git show <hash>to confirm it is the right commit.Run
git branch recovered-branch <hash>to recreate the branch.Switch to it:
git switch recovered-branch.Push to remote:
git push origin recovered-branch.
Prevention
Push branches to remote before deleting them locally — remote copies serve as backups.
Use
git branch -d(safe delete) instead ofgit branch -D— Git will warn you if the branch is not fully merged.On GitHub/GitLab, avoid immediately deleting branches after merging a PR — the platform keeps them with a restore button.
Consider extending reflog expiry in teams:
git config --global gc.reflogExpire "180 days".