Skip to content

Navid's Blog

Ideas, Experiments, and Lessons Learned

Menu
Menu
Dark laptop with code on the screen late in the afternoon

I Force-Pushed to Main on a Friday — Here’s What Happened Next

Posted on September 1, 2026 by Navid

One command. Eleven keystrokes. And somewhere between my keyboard and GitHub, a full day of my teammate’s work quietly stopped existing.

It came back, don’t worry, but I aged about four years in the process.

The Setup

Our main had moved ahead, so I rebased, ran the tests, everything green. The push got rejected because my local main was behind, and instead of pulling first like a normal person I got impatient and did the thing you’re not supposed to do.

git push --force origin main

Yes, straight to main. Yes, we have branch protection. No, I don’t want to talk about how I had the rights to bypass it. (Small team, we trusted each other, which sounds sweet until one of us turns out to be me.)

The Spiral

For about ninety seconds I felt great. Branch pushed, CI running, weekend loading.

Then Slack lit up. Sara, our backend dev, had pushed three commits to main an hour earlier. Commits that no longer existed on the remote, because my push had flattened them. Her message was just my name followed by a question mark, which is somehow the politest way anyone has ever told me I ruined their day.

I did the panic lap first: checked the CI logs, checked the PR list, stared at GitHub like it would apologize. Nothing.

The Discovery

Here’s the thing that saved us, and I didn’t even know it at the time: Sara hadn’t closed her laptop.

Her local branch still had all three commits, sitting in her own reflog, completely untouched by my mistake. A force push doesn’t actually delete anything; it just moves the remote’s pointer. She pushed them back, main was whole again, and the rescue took about four minutes.

So the fix isn’t some fancy recovery tool. Git keeps objects around long after branches stop pointing at them, which means the fastest backup is usually the person who wrote the code.

I’ve never been so grateful for someone logging off at five.

What I Learned

  • Force with a lease. --force-with-lease refuses the push if the remote has commits you haven’t seen. One extra flag and Sara keeps her Friday.
  • Branch protection exists for a reason. Being able to bypass it “just this once” is exactly the wrong instinct, and I had that instinct.
  • Reflog is the safety net. Locally, “lost” commits stick around for a good while.
  • Rebase feature branches, not main. I don’t need main to be mine. Honestly, nobody needs main to be mine.

What I’d Do Different

  1. Pull before pushing. The entire disaster was me skipping one command because I wanted to beat the 4pm traffic.
  2. Turn on required reviews for main and delete my bypass rights, and yes, that was my own suggestion, which Sara enjoyed a little too much.
  3. If a push gets rejected, stop and read the reason.

So yeah. Eleven keystrokes and a full team panic, all because I couldn’t wait for one pull to finish. The force-with-lease habit stuck, at least. Sara got a coffee voucher out of it, so she’s over it. Mostly.

External Resources

  • git-push docs, the –force-with-lease section
  • Pro Git, chapter on data recovery and reflog
  • GitHub docs on branch rulesets

Categories

  • AI Experiments
  • Coding
  • Debugging Stories
  • Hot Takes
  • Ideas
  • Lessons Learned
  • Productivity
  • Project Management
  • Systems & Architecture
  • Uncategorized
  • Vibe Coding

Recent Posts

  • 5 ORM Mistakes That Pushed Me Back to Raw SQL
  • Norway Vanished From Our App for Two Days — It Was One Unquoted Line
  • I Ignored a Deprecation Warning for 11 Months — It Worked Until It Didn’t
  • Why I Stopped Time-Blocking (And What I Do Instead)
  • I Vibe-Coded a Tool in One Afternoon — It Died on Its First Real User