7 Git Commands That Saved Me From Disaster
Learn: 7 Git Commands That Saved Me From Disaster
Welcome to TopperBlog! 👋
I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.
🎯 What I Write About:
• AI/ML Engineering & LLMs
• Web3 & Blockchain Development
• System Design & Architecture
• Interview Preparation (FAANG)
• Freelancing & Remote Work
• Modern Tech Stacks (Next.js, React, Rust, TypeScript)
• Performance Optimization & Best Practices
💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.
📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.
🌐 Let's connect and grow together in this amazing tech journey!
#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering
7 Git Commands That Saved Me From Disaster: Recovery Techniques Every Developer Needs
Introduction: The 3 AM Panic Attack
I'll never forget that Friday night at 2:47 AM. I was putting the finishing touches on a critical feature for Monday's product launch when I executed what I thought was a harmless git reset --hard. Within seconds, three days of work vanished into the digital void. My heart sank. My palms got sweaty. I frantically Googled "how to undo git reset" while my coffee went cold.
That night changed how I approach Git forever. I learned that Git isn't just a version control system—it's a safety net with hidden superpowers that can rescue you from almost any disaster. Over the past eight years of development, I've accumulated a toolkit of Git recovery commands that have saved my bacon more times than I'd like to admit.
Today, I'm sharing these seven lifesaving Git commands with you. Whether you've accidentally deleted commits, pushed sensitive data, or completely messed up your branch, these techniques will help you sleep better at night knowing you can recover from almost anything.
The Problem: When Good Developers Make Bad Commits
Let's be honest—we've all been there. You're in the zone, coding at lightning speed, and then:
- You commit API keys or passwords to your repository
- You accidentally delete an entire feature branch
- You merge the wrong branches and create a tangled mess
- You rebase incorrectly and lose important commits
- You push broken code to production
- You overwrite someone else's work with a force push
According to a 2023 Stack Overflow survey, 68% of developers have experienced a "Git disaster" at least once in their career. The difference between a minor hiccup and a career-defining catastrophe often comes down to knowing the right recovery commands.
The good news? Git is incredibly forgiving. Almost nothing is truly lost in Git—you just need to know where to look and what commands to use.
1. Git Reflog: Your Time Machine for Lost Commits
What It Does
git reflog is hands-down the most powerful recovery command in your Git arsenal. It's essentially a chronological log of every action that moved your HEAD pointer—commits, checkouts, resets, merges, everything.
My Story
Remember that 3 AM disaster I mentioned? git reflog saved me. After my catastrophic git reset --hard, I discovered that Git keeps a reference log of where HEAD has been. Every commit I thought I'd lost was still there, just orphaned.
How to Use It
# View your reflog
git reflog
# Output looks like this:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# e4f5g6h HEAD@{1}: commit: Add user authentication
# i7j8k9l HEAD@{2}: commit: Fix login bug
# m0n1o2p HEAD@{3}: commit: Update API endpoints
Recovery Steps
# Find the commit you want to recover
git reflog
# Reset to that commit using the reference
git reset --hard HEAD@{2}
# Or use the commit hash
git reset --hard e4f5g6h
Pro Tips
- Reflog entries expire after 90 days by default (30 days for unreachable commits)
- Use
git reflog show branch-nameto see reflog for specific branches - Combine with
git log --all --oneline --graphto visualize your history
2. Git Fsck: Finding Dangling Commits
What It Does
When git reflog isn't enough (maybe you're past the 90-day window), git fsck (file system check) can find "dangling" or "unreachable" commits that aren't referenced by any branch or tag.
Real-World Scenario
Last year, I was cleaning up an old repository and accidentally deleted a branch that contained experimental features. Three months later, I needed that code. Reflog had expired, but git fsck came to the rescue.
How to Use It
# Find all dangling commits
git fsck --lost-found
# More readable output
git fsck --lost-found | grep commit
# Examine a dangling commit
git show <commit-hash>
# Recover it by creating a new branch
git branch recovered-branch <commit-hash>
Advanced Recovery
# Find all dangling commits and show their messages
git fsck --lost-found | grep commit | cut -d' ' -f3 | xargs git log --oneline -1
# Create branches for multiple dangling commits
for commit in $(git fsck --lost-found | grep commit | cut -d' ' -f3); do
git branch "recovered-$(date +%s)" $commit
done
3. Git Revert: The Safe Undo Button
What It Does
Unlike git reset, which rewrites history, git revert creates a new commit that undoes the changes from a previous commit. This is crucial when you've already pushed to a shared branch.
When I Use It
I once pushed a commit that broke our production API. Twenty developers had already pulled the changes. Using git reset would have created chaos. git revert saved the day by creating a clean undo commit that everyone could pull normally.
How to Use It
# Revert the most recent commit
git revert HEAD
# Revert a specific commit
git revert a1b2c3d
# Revert multiple commits
git revert HEAD~3..HEAD
# Revert without creating a commit immediately (useful for batch reverts)
git revert -n HEAD~3..HEAD
git commit -m "Revert last 3 commits"
Revert vs Reset: Key Differences
# Reset (rewrites history - dangerous on shared branches)
git reset --hard HEAD~1
# Revert (creates new commit - safe for shared branches)
git revert HEAD
4. Git Cherry-Pick: Selective Commit Recovery
What It Does
git cherry-pick lets you apply specific commits from one branch to another. It's perfect when you committed to the wrong branch or need to selectively recover work.
My Use Case
I once spent an entire afternoon building a feature on the develop branch, only to realize it should have been on a feature branch. Cherry-pick let me move those commits without redoing the work.
How to Use It
# Apply a single commit to your current branch
git cherry-pick a1b2c3d
# Apply multiple commits
git cherry-pick a1b2c3d e4f5g6h
# Apply a range of commits
git cherry-pick start-commit^..end-commit
# Cherry-pick without committing (to modify first)
git cherry-pick -n a1b2c3d
Handling Conflicts
# If conflicts occur during cherry-pick
git status # See conflicting files
# Fix conflicts manually
git add .
git cherry-pick --continue
# Or abort the cherry-pick
git cherry-pick --abort
5. Git Stash: Emergency Save for Uncommitted Work
What It Does
git stash temporarily shelves your uncommitted changes, letting you switch contexts without committing half-finished work. It's saved me countless times when urgent bugs interrupt my flow.
Real-World Example
You're mid-feature when your manager asks you to fix a critical production bug. You can't commit your incomplete work, but you need a clean working directory.
How to Use It
# Stash your current changes
git stash
# Stash with a descriptive message
git stash save "WIP: user authentication feature"
# List all stashes
git stash list
# Apply the most recent stash
git stash apply
# Apply and remove the stash
git stash pop
# Apply a specific stash
git stash apply stash@{2}
# View stash contents without applying
git stash show -p stash@{0}
Advanced Stash Techniques
# Stash including untracked files
git stash -u
# Stash including ignored files
git stash -a
# Create a branch from a stash
git stash branch new-feature-branch stash@{1}
# Delete a specific stash
git stash drop stash@{0}
# Clear all stashes
git stash clear
6. Git Reset: The Nuclear Option (Use Wisely)
What It Does
git reset moves your branch pointer to a different commit. It comes in three flavors: --soft, --mixed, and --hard, each with different levels of destructiveness.
When to Use Each Mode
I learned these distinctions the hard way. Here's what each mode does:
The Three Reset Modes
# --soft: Move HEAD, keep staging area and working directory
git reset --soft HEAD~1
# Use when: You want to recommit with a different message
# --mixed (default): Move HEAD, reset staging, keep working directory
git reset HEAD~1
# Use when: You want to unstage files but keep changes
# --hard: Move HEAD, reset staging AND working directory
git reset --hard HEAD~1
# Use when: You want to completely discard commits (DANGEROUS!)
Safe Reset Workflow
# Always check what you're about to reset
git log --oneline -5
# Create a backup branch first
git branch backup-before-reset
# Then reset
git reset --hard HEAD~3
# If you mess up, recover from backup
git reset --hard backup-before-reset
Undoing a Reset
# Use reflog to find the commit before reset
git reflog
# Reset back to that point
git reset --hard HEAD@{1}
7. Git Filter-Branch & BFG: Removing Sensitive Data
What It Does
Sometimes you commit something you absolutely shouldn't have—API keys, passwords, or large binary files. These commands rewrite history to remove sensitive data from all commits.
My Horror Story
I once committed our entire .env file with production database credentials to a public GitHub repository. Within minutes, I had automated bots trying to access our systems. I needed to remove that data from history immediately.
Using BFG Repo-Cleaner (Recommended)
BFG is faster and simpler than git filter-branch:
# Install BFG (Mac)
brew install bfg
# Clone a fresh copy of your repo
git clone --mirror https://github.com/user/repo.git
# Remove a specific file from all commits
bfg --delete-files config.env repo.git
# Remove all files larger than 100MB
bfg --strip-blobs-bigger-than 100M repo.git
# Replace passwords in all commits
bfg --replace-text passwords.txt repo.git
# Clean up and push
cd repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force
Using Git Filter-Branch (Built-in)
# Remove a file from all commits
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/sensitive-file.txt" \
--prune-empty --tag-name-filter cat -- --all
# Remove a directory
git filter-branch --force --index-filter \
"git rm -r --cached --ignore-unmatch path/to/directory" \
--prune-empty --tag-name-filter cat -- --all
# Force push to remote
git push origin --force --all
git push origin --force --tags
Critical Post-Removal Steps
# Notify all collaborators to rebase their work
# Invalidate the exposed credentials immediately
# Consider the data compromised even after removal
Comparison Table: When to Use Each Recovery Command
| Command | Best For | Rewrites History? | Safe for Shared Branches? | Difficulty |
git reflog | Finding lost commits after reset/rebase | No | Yes | Easy |
git fsck | Recovering very old deleted commits | No | Yes | Medium |
git revert | Undoing pushed commits safely | No | Yes | Easy |
git cherry-pick | Moving commits between branches | No | Yes | Easy |
git stash | Temporarily saving uncommitted work | No | Yes | Easy |
git reset | Undoing local commits | Yes | No | Medium |
git filter-branch/BFG | Removing sensitive data from history | Yes | No | Hard |
Prevention: Avoiding Disasters in the First Place
While recovery commands are essential, prevention is better than cure. Here are my hard-learned lessons:
Git Aliases for Safety
# Add these to your ~/.gitconfig
[alias]
# Safer force push
force-push = push --force-with-lease
# Undo last commit but keep changes
undo = reset HEAD~1 --mixed
# View history with graph
hist = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
# Show what would be pushed
dry-push = push --dry-run
Pre-Commit Hooks
# Create .git/hooks/pre-commit
#!/bin/bash
# Check for common sensitive patterns
if git diff --cached | grep -E 'API_KEY|PASSWORD|SECRET'; then
echo "⚠️ Warning: Possible sensitive data detected!"
echo "Review your changes and use git commit --no-verify to override"
exit 1
fi
Backup Strategies
# Create a backup branch before risky operations
git branch backup-$(date +%Y%m%d-%H%M%S)
# Or use tags
git tag backup-before-rebase
FAQ Section
How long does Git keep deleted commits?
Git keeps unreachable commits for 30 days by default and reflog entries for 90 days. You can configure this with:
# Keep reflog entries for 180 days
git config gc.reflogExpire 180.days
# Keep unreachable commits for 60 days
git config gc.reflogExpireUnreachable 60.days
However, once git gc (garbage collection) runs and these timeframes pass, the commits are permanently deleted.
Can I recover a deleted branch?
Yes! If you deleted a branch recently, use git reflog to find the commit where the branch pointed, then recreate it:
# Find the deleted branch in reflog
git reflog | grep "branch-name"
# Recreate the branch
git branch branch-name <commit-hash>
If the branch was deleted a while ago, try git fsck --lost-found to find dangling commits.
What's the difference between git revert and git reset?
Git reset moves your branch pointer backward and can erase commits from history. It's great for local changes but dangerous for shared branches.
Git revert creates a new commit that undoes previous changes, preserving history. It's safe for shared branches because it doesn't rewrite history—everyone can pull the revert commit normally.
Use reset for local mistakes, revert for pushed commits.
I force-pushed and overwrote someone's work. Can I recover it?
If the other person still has their local copy, they haven't lost anything—they just need to force-push their version back (after coordinating with the team).
If their work was only on the remote and you overwrote it, check the remote's reflog (if you have server access) or contact your Git hosting provider immediately. GitHub, GitLab, and Bitbucket keep deleted data for a limited time and may be able to help.
Prevention tip: Use git push --force-with-lease instead of --force. It only succeeds if no one else has pushed changes.
How do I recover uncommitted changes I accidentally deleted?
This is tricky. If you used git reset --hard or git clean -fd, uncommitted changes are usually gone forever because they were never tracked by Git.
However, you might get lucky:
- Check your IDE's local history (VS Code, IntelliJ, etc. keep temporary backups)
- Look for temporary files in
.git/directory - Use file recovery tools on your operating system
- Check if you have automatic backups enabled (Time Machine, Windows File History, etc.)
This is why I commit early and often, even with "WIP" messages. You can always clean up commits later with interactive rebase.
Conclusion: Your Git Recovery Action Plan
Git disasters feel catastrophic in the moment, but with the right knowledge, they're almost always recoverable. Here's your action plan for the next time disaster strikes:
Immediate Steps When Something Goes Wrong
- Don't panic and don't make it worse - Stop typing commands randomly
- Check
git reflogfirst - 90% of problems are solved here - Create a backup branch - Before attempting recovery:
git branch emergency-backup - Document what happened - Write down the commands you ran
- Try the least destructive solution first - Revert before reset, reset --soft before --hard
Build Your Safety Net Today
# Set up helpful aliases
git config --global alias.undo 'reset HEAD~1 --mixed'
git config --global alias.save '!git add -A && git commit -m "SAVEPOINT"'
git config --global alias.wip '!git add -u && git commit -m "WIP"'
# Configure longer reflog retention
git config --global gc.reflogExpire 180.days
# Always use safer force push
git config --global alias.force-push 'push --force-with-lease'
Practice in a Safe Environment
Don't wait for a real disaster to learn these commands. Create a test repository and practice:
# Create a practice repo
mkdir git-practice && cd git-practice
git init
# Make some commits
echo "test" > file.txt && git add . && git commit -m "First commit"
echo "test2" >> file.txt && git add . && git commit -m "Second commit"
# Practice recovery techniques
git reset --hard HEAD~1 # Delete a commit
git reflog # Find it
git reset --hard HEAD@{1} # Recover it
The seven commands I've shared—git reflog, git fsck, git revert, git cherry-pick, git stash, git reset, and git filter-branch/BFG—have saved me from countless disasters over the years. They've turned potential career-ending mistakes into minor inconveniences.
Remember: Git is designed to preserve your work. Almost nothing is truly lost—you just need to know where to look. Bookmark this article, practice these commands, and sleep better knowing you can recover from almost any Git disaster.
Now go forth and commit with confidence. And when disaster inevitably strikes, you'll know exactly what to do.
What Git disaster have you faced? Share your story in the comments below, and let's learn from each other's mistakes!