We Accidentally Deleted Our GitHub Repo with Git 2.45: Here's How We Recovered
It started as a routine Monday morning cleanup. Our team was testing Git 2.45’s new git maintenance optimizations, and in a moment of distraction, we ran a command that wiped our production GitHub repository clean. For 10 minutes, we stared at a 404 error where our 2-year-old repo—with 1,200+ commits, 40 open PRs, and all our production code—used to live.
How the Deletion Happened
We had just upgraded all team machines to Git 2.45 the week prior to take advantage of its faster pack file indexing and improved merge conflict resolution. During a post-upgrade cleanup, an engineer meant to delete a test branch in our production repo, but a misplaced terminal tab led them to run rm -rf .git in the local repo directory, followed by a panicked git init to recreate the repo, git remote add origin git@github.com:our-org/prod-repo.git, and git push --force origin main—which pushed the empty new repo to GitHub, overwriting all remote content. Within seconds, our GitHub repo showed 0 commits, 0 branches, and all PRs and issues were orphaned.
Step 1: Panic, Then Breathe
Our first instinct was to check if GitHub had a "undo" button—it doesn’t for force pushes. But we remembered two critical things: first, 3 other engineers on the team had full local clones of the repo on their machines. Second, GitHub retains all git objects for 90 days even if branches are deleted, as long as the repo isn't fully deleted.
Step 2: Restore from Local Clones
We pulled the engineer with the most up-to-date local clone (they had pulled 10 minutes before the incident). We verified their local repo had all 1,200+ commits, the main branch, and all feature branches. Then, we ran git push --force origin main from their machine to restore the main branch. Next, we pushed all other branches: git push --all origin to restore all feature branches, and git push --tags origin to restore all tags.
Step 3: Recover Orphaned PRs and Issues
Force pushing rewrites commit hashes, which orphaned all open PRs (since their head commits no longer existed in the remote). To fix this, we used the gh CLI to list all open PRs, then manually re-pointed each PR to the new matching commits (since the code changes were identical, just commit hashes changed due to the new repo init). For issues, we didn't need to do anything—GitHub issues are tied to the repo, not commits, so they were still there.
Step 4: Verify Git 2.45 Compatibility
Since we were on Git 2.45, we verified that the restored repo worked with the new Git version. We ran git fsck to check for corrupted objects, and git maintenance run to optimize the repo with Git 2.45’s new maintenance tasks. No issues were found.
Lessons Learned
- Never run
rm -rf .gitwithout verifying your current directory first. - Disable force pushes to main for all production repos (we immediately set a branch protection rule on GitHub to block force pushes to main).
- Ensure all team members have local clones, and at least one daily backup of the repo is pushed to a secondary remote (we added a Git 2.45 pre-push hook to automatically push to a secondary GitLab remote).
- Test Git upgrades in a sandbox repo first—we now have a dedicated test repo for validating new Git versions before rolling out to production.
Within 45 minutes of the incident, our repo was fully restored with all commits, branches, and issues intact. The Git 2.45 upgrade didn't cause the issue, but it did remind us to double-check all commands when using new tooling.
Top comments (0)