RECOVERY PLAYBOOK
Recovery Playbook¶
Purpose¶
This document provides step-by-step recovery procedures in case a bad PR merges or destructive changes are introduced to the repository.
Important: Always prefer non-destructive revert operations over hard resets when possible.
Scenario 1: Bad PR Merged (Prefer Revert)¶
If a bad commit has been merged to main:
Step 1: Identify the bad commit(s)¶
# View recent commit history
git log --oneline --decorate --graph -20
# Or view with more detail
git log --oneline --decorate --graph --all
Step 2: Revert the commit¶
For a single commit:
# Revert creates a new inverse commit (preserves history)
git revert <bad_sha>
# Push the revert
git push origin main
For a merge commit:
# Revert merge commit (use -m 1 to revert to first parent)
git revert -m 1 <merge_commit_sha>
# Push the revert
git push origin main
For multiple commits:
# Revert a range of commits (newest first)
git revert <newest_bad_sha>..<oldest_bad_sha>
# Or revert individually
git revert <sha1>
git revert <sha2>
git revert <sha3>
# Push all reverts
git push origin main
Scenario 2: Bad PR Open (Not Merged)¶
If a destructive PR is still open:
- Close the PR via GitHub UI (do not merge)
- Delete the branch if safe to do so
- Create a new PR with the correct changes
Scenario 3: Main Branch Truly Wiped (Last Resort)¶
⚠️ WARNING: Only use this if reverts are not possible or if the repository state is completely corrupted.
Step 1: Identify the last good commit¶
# View reflog to find the last known good state
git reflog
# Or check remote state
git fetch origin
git log origin/main --oneline -20
Step 2: Hard reset to good commit¶
# Switch to main branch
git checkout main
# Reset to the last good commit (use exact SHA you trust)
git reset --hard <good_sha>
# Force push with lease (safer than --force)
git push --force-with-lease origin main
Why --force-with-lease? It prevents overwriting remote changes if someone else pushed while you were fixing things.
Scenario 4: Recover Specific Deleted Files¶
If you need to restore specific files without reverting entire commits:
Step 1: Create a restoration branch¶
Step 2: Restore files from a good commit¶
# Restore a single file
git checkout <good_sha> -- path/to/file
# Restore an entire directory
git checkout <good_sha> -- path/to/important/dir
# Restore multiple paths
git checkout <good_sha> -- path/to/file1 path/to/file2 path/to/dir/
Step 3: Commit and push¶
git add .
git commit -m "restore: bring back files from <good_sha>"
git push -u origin restore-files
Step 4: Open PR for review¶
Open a PR to merge restore-files into main and ensure all guardrails pass.
Quick Reference Commands¶
# View recent commits
git log --oneline --decorate --graph -10
# Revert a commit
git revert <sha>
# Revert a merge commit
git revert -m 1 <merge_sha>
# View reflog (for finding lost commits)
git reflog
# Hard reset to a commit (dangerous!)
git reset --hard <sha>
# Restore specific files
git checkout <good_sha> -- path/to/file
# Safe force push
git push --force-with-lease origin main
Prevention¶
These guardrails prevent destructive changes:
- Anti-nuke workflow (
.github/workflows/anti-nuke.yml) - Blocks PRs with excessive deletions - Codex policy (
.github/codex-policy.yml) - Enforces additive-only mode - Branch protection - Requires PRs, blocks force-push, requires approvals
- GI gates - Ensures integrity checks pass before merge
Always review PRs carefully, especially those with deletions in protected paths.
Emergency Contacts¶
If you need help recovering: - Check .github/CODEOWNERS for code owners - Review CI/CD logs for what changed - Use git reflog to find lost commits
Last updated: 2025-01-27