A developer’s nightmare while building DuesTracker and the hidden feature that saved everything
🎯 TL;DR
I spent an entire morning writing beautiful React components for DuesTracker (my university’s class payment management system). A git rebase conflict corrupted everything. My code vanished. Git couldn’t help because the files were never committed. But VS Code’s Local History feature — one I never knew existed — saved every single line.
🌅 The Morning: Everything Was Perfect
January 5th, 2026. I was in the zone.
For context, I’ve been building DuesTracker — a React + TypeScript + Supabase app to help manage class payment dues for ECE students at my university. Today was supposed to be a big milestone.
I had just finished implementing some seriously cool features:
- ✨ ProfessionalDropdown component with search, multi-select, keyboard navigation, and Framer Motion animations
- 📄 Complete PDF Export utility using jsPDF with professional headers and styled tables
- 🔐 Security configuration module with domain validation
- 🔄 DashboardSwitcher component for seamless admin/student view transitions
- 🛡️ Build protection with Terser minification
These weren’t just quick hacks — they were production-ready, beautifully crafted components.
Then I decided to commit:
“Alright, let me commit all these changes and push to GitHub”
Little did I know, those words would trigger a cascade of events that nearly cost me everything.
💀 The Disaster: When Git Becomes Your Enemy
Here’s what happened:
$ git status
interactive rebase in progress; onto d520815
⚠️ Wait, what? An interactive rebase was somehow in progress. I hadn’t started one.
No problem, I thought:
$ git rebase --abort
$ git pull --rebase origin main
The terminal showed success:
Successfully rebased and updated refs/heads/main.
Dropped 8fdd4db (duplicate commit - already in upstream)
But when I looked at my files…
They were gone.
-
ProfessionalDropdown.tsx— Gone 💔 -
pdfExport.ts— Gone 💔 -
security.ts— Gone 💔 -
DashboardSwitcher.tsx— Gone 💔 - All my
vite.config.tschanges — Reverted 💔
Hours of work. Vanished. In seconds.
😰 The Panic: Checking Git Reflog
My heart was racing. But I knew about git reflog:
$ git reflog -30
18afa92 HEAD@{0}: pull --rebase origin main (finish)
8fdd4db HEAD@{1}: rebase (abort): returning to refs/heads/main
18afa92 HEAD@{2}: commit: resolved a conflict
8fdd4db HEAD@{3}: commit: fix: scanner lifecycle, diagnostics...
Found it! 8fdd4db! Let me cherry-pick:
$ git cherry-pick 8fdd4db
Result:
The previous cherry-pick is now empty, possibly due to conflict resolution.
The Devastating Realization
The commit was already in upstream. But here’s the problem:
The new files I created this morning were NEVER committed.
They existed only in my working directory. Now they were gone.
- ❌ Git reflog couldn’t help
- ❌ Git stash was empty
- ❌ No
.gitbackup of uncommitted files
I was about to accept my fate and rewrite everything from memory…
💡 The Discovery: VS Code’s Secret Weapon
While debugging with my AI assistant, we discovered something I had completely overlooked:
VS Code has a local history feature!
I quickly checked:
Get-ChildItem -Path "$env:APPDATA\Code\User\History" -Recurse
And there it was. Hundreds of files.
VS Code had been silently saving versions of every file I edited — automatically, in the background, without me ever knowing.
C:\Users\YourUsername\AppData\Roaming\Code\User\History\
├── -33ad014b\ # ProfessionalDropdown.tsx
│ ├── entries.json
│ ├── H746.tsx # 12:26 PM ⏰
│ ├── Itgi.tsx # 12:15 PM ⏰
├── -3718bc8b\ # pdfExport.ts
│ ├── EM0w.ts # 12:20 PM ⏰
└── ...
Each folder had timestamped backups. The entries.json mapped to the original file path.
My code wasn’t lost. VS Code had my back the entire time. 🙌
🔧 The Recovery: Bringing Everything Back
Step 1️⃣: Find the History Folders
Get-ChildItem -Path "$env:APPDATA\Code\User\History" -Recurse -Filter "entries.json" |
ForEach-Object {
$content = Get-Content $_.FullName | ConvertFrom-Json
if ($content.resource -like "*Class-dues-tracker*") {
Write-Output "$($_.Directory.Name): $($content.resource)"
}
}
Step 2️⃣: Get the Latest Version
$latestFile = Get-ChildItem -Path $historyPath -File |
Where-Object { $_.Name -ne "entries.json" } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Step 3️⃣: Automated Recovery Script
$mappings = @{
"-33ad014b" = "src/components/ui/ProfessionalDropdown.tsx"
"-3718bc8b" = "src/utils/pdfExport.ts"
"6319c950" = "src/config/security.ts"
"-61ef17a9" = "src/components/DashboardSwitcher.tsx"
"7ee7ef46" = "vite.config.ts"
}
foreach ($folder in $mappings.Keys) {
$histPath = "$env:APPDATA\Code\User\History\$folder"
$destPath = $mappings[$folder]
$latestFile = Get-ChildItem -Path $histPath -File |
Where-Object { $_.Name -ne "entries.json" } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
Copy-Item -Path $latestFile.FullName -Destination $destPath -Force
Write-Output "✅ Restored: $destPath"
}
✨ Result:
✅ Restored: src/components/ui/ProfessionalDropdown.tsx
✅ Restored: src/utils/pdfExport.ts
✅ Restored: src/config/security.ts
✅ Restored: src/components/DashboardSwitcher.tsx
✅ Restored: vite.config.ts
Every. Single. Line. Recovered. 🎉
📊 The Final Commit
27 files changed, 5976 insertions(+), 552 deletions(-)
create mode 100644 LICENSE
create mode 100644 src/components/DashboardSwitcher.tsx
create mode 100644 src/components/ui/ProfessionalDropdown.tsx
create mode 100644 src/config/security.ts
create mode 100644 src/utils/pdfExport.ts
5,976 lines of code saved. Not rewritten from memory. Not approximated. The exact code I wrote.
🎓 Lessons Learned: How to Never Lose Code Again
1. 💾 Commit Early, Commit Often
This is Git 101, but I got complacent.
New Rule: If you’ve written more than 30 minutes of code, commit it.
git commit -m "WIP: feature in progress"
Even imperfect commits are better than no commits.
2. 🕐 Know About VS Code Local History
VS Code has been saving your file history this whole time!
Access it:
- Right-click any file → “Open Timeline” (bottom of Explorer)
- Or navigate to:
%APPDATA%\Code\User\History\(Windows)
Configure it:
{
"workbench.localHistory.enabled": true,
"workbench.localHistory.maxFileEntries": 50,
"workbench.localHistory.maxFileSize": 256
}
3. ⚠️ Never Force Git Operations Without Understanding
Commands like git rebase, git reset --hard, and git clean can destroy uncommitted work.
Before running them:
- Check
git statusfirst - Commit or stash everything
- Create a backup branch:
git branch backup-just-in-case
4. 📦 Use Git Stash Before Risky Operations
# Before any risky git operation
git stash push -m "backup before rebase"
# If something went wrong
git stash pop
5. 💾 Set Up Auto-Save
In VS Code settings:
{
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000
}
This ensures Local History captures your changes.
6. 🪝 Consider Git Hooks for Reminders
Create .git/hooks/pre-commit:
#!/bin/bash
UNCOMMITTED=$(git diff --stat | wc -l)
if [ "$UNCOMMITTED" -gt 100 ]; then
echo "⚠️ You have $UNCOMMITTED lines of uncommitted changes!"
echo "Consider committing more frequently."
fi
📂 Where VS Code Stores Local History
| OS | Path |
|---|---|
| Windows | %APPDATA%\Code\User\History\ |
| macOS | ~/Library/Application Support/Code/User/History/ |
| Linux | ~/.config/Code/User/History/ |
Each edited file gets a folder with timestamped backups.
🛠️ Quick Recovery Script (Save for Emergencies!)
# recover-from-vscode-history.ps1
param(
[string]$SearchPattern = "*your-project*",
[string]$OutputDir = "./recovered"
)
$historyBase = "$env:APPDATA\Code\User\History"
New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null
Get-ChildItem -Path $historyBase -Recurse -Filter "entries.json" | ForEach-Object {
$content = Get-Content $_.FullName -Raw | ConvertFrom-Json
if ($content.resource -like $SearchPattern) {
$latestFile = Get-ChildItem -Path $_.Directory.FullName -File |
Where-Object { $_.Name -ne "entries.json" } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($latestFile) {
$fileName = Split-Path $content.resource -Leaf
$destPath = Join-Path $OutputDir $fileName
Copy-Item -Path $latestFile.FullName -Destination $destPath -Force
Write-Host "✅ Recovered: $fileName" -ForegroundColor Green
}
}
}
Write-Host "`n📁 Files recovered to: $OutputDir" -ForegroundColor Cyan
Usage:
.\recover-from-vscode-history.ps1 -SearchPattern "*my-project*" -OutputDir "./recovered"
💭 Final Thoughts
This experience was terrifying but educational. I went from thinking I’d lost an entire morning’s work to recovering everything in minutes.
Key Takeaways:
- ✅ Git is powerful but only protects committed code
- ✅ VS Code Local History is your silent guardian
- ✅ Commit frequently — “WIP” commits are perfectly fine
- ✅ Know your recovery options BEFORE you need them
The next time you’re deep in a coding session, remember:
Commit early, commit often, and know that VS Code has your back.
🚀 About DuesTracker
This experience happened while building DuesTracker — a React + TypeScript + Supabase application for managing class payment dues at my university. It’s been a journey of constant learning, from React patterns to Supabase RLS policies, and now… disaster recovery.
Sometimes the best solutions aren’t complex — they’re hidden features in tools you already use every day.
💬 Your Turn!
Have you ever lost code and recovered it in an unexpected way? Share your war stories in the comments! 👇
What’s your biggest coding disaster? How did you recover?
Follow my journey building DuesTracker for more development insights, lessons learned, and technical deep-dives!
Tags: #git #vscode #webdev #javascript #typescript #react #devtips #productivity #beginners #programming
Top comments (0)