You Pushed to Main by Accident. Here Is What to Do Next.

by Arif Ikhsanudin, Backend Developer

The Next Five Minutes Matter

You ran git push and immediately realized you were on main, not your feature branch. Your stomach drops. Your first instinct is to force push to erase the evidence. Stop. That instinct is wrong and will make the situation significantly worse if anyone has pulled in the time between your push and your force push.

Here is the ordered response that minimizes damage.

Step 1: Assess What You Pushed

Before doing anything else, understand the situation. What did you push?

# What just went to main that shouldn't be there?
git log origin/main~1..origin/main --oneline
# Shows the commits that just landed on main

# How different is it from what main should look like?
git diff origin/main~1 origin/main --stat

If you pushed a single commit containing work-in-progress code: containable. If you pushed three weeks of feature branch commits: more complex, but still manageable. If you pushed code that includes credentials, API keys, or passwords: immediate priority is different — those secrets need to be rotated before anything else happens, because they may have already been scraped.

Step 2: Has Anyone Pulled?

Check your team's activity. If it's 3am and the team is in a different timezone, you probably have a window. If it's 2pm on a Monday and there's active CI running: assume people are working and may have pulled.

If CI runs on every push to main: CI has already seen the commits and may have deployed them. Check your CI dashboard immediately.

Step 3: The Response Depends on Whether CI/CD Already Ran

If CI/CD has not deployed yet

You have the cleanest option: revert the commit.

# Revert is safe — it creates a new commit that undoes the change
# It does not rewrite history
git revert HEAD --no-edit
git push origin main

git revert creates a new commit that inverts the changes from the commit you're reverting. It doesn't touch history. Anyone who already pulled the bad commit will get the revert when they pull again. Their history will show the bad commit followed by its revert, which is honest and recoverable.

If CI/CD already deployed

Now you have two problems: the code is in production, and the commit is in main. Prioritize in order:

  1. Evaluate whether the deployed code is causing user-visible problems. If yes, roll back the deployment immediately using your deployment tool's rollback mechanism (Kubernetes: kubectl rollout undo, Heroku: heroku releases:rollback, etc.)
  2. After the deployment situation is stable, revert the commit in main.

Do not spend time on Git cleanup while the deployment is actively harming users.

Step 4: What About Force Push?

Force pushing to main (git push --force origin main) rewrites history. This removes the bad commits from the remote branch as if they never existed.

The risk: if anyone pulled between your original push and your force push, their local main now has the commits that no longer exist on the remote. The next time they push, they'll get a "non-fast-forward" error. If they git pull at that point, they'll re-introduce your bad commits to the remote. The history becomes confused.

Force push to main is appropriate only when:

  • You're certain nobody has pulled (early hours, you're the only one awake)
  • The push contained sensitive data that must be erased from history (credentials, PII)
  • You're the only developer on the repository

For the sensitive data case, a force push still doesn't fully solve the problem. GitHub, GitLab, and other forges cache content. If the credentials were in a public repository for any length of time, assume they're compromised and rotate them regardless.

If you force push, immediately notify the team: "I force pushed to main at [time] to remove an accidental commit. If you've pulled in the last [N] minutes, run git fetch origin && git reset --hard origin/main to get back in sync."

# Use --force-with-lease instead of --force as a safer alternative
# It will fail if someone else pushed after your bad push
git push --force-with-lease origin main

Step 5: After Recovery, Understand Why It Happened

Accidental pushes to main usually happen for one of a few reasons:

  • You were on main and didn't notice (git status before committing is a habit worth building)
  • The remote's main branch protection rules weren't enabled
  • You intended to push to a branch but the upstream wasn't set

The easiest prevention: enable branch protection on main. GitHub's Settings → Branches → Branch protection rules → "Require a pull request before merging." This makes git push origin main fail unless you have bypassed the protection (usually only available to admins).

# Check which branch you're on before committing
git status

# Or configure your shell prompt to show the current branch
# Most shells support this via $(__git_ps1) or equivalent

If you need to regularly push to main (as an admin bypassing protection), add a pre-push hook that warns you:

#!/bin/sh
# .git/hooks/pre-push
branch=$(git symbolic-ref HEAD 2>/dev/null)
if [ "$branch" = "refs/heads/main" ]; then
    echo "WARNING: You are about to push directly to main."
    printf "Are you sure? (y/N): "
    read confirm
    if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
        echo "Push aborted."
        exit 1
    fi
fi

The Calm Response Is the Right Response

The worst thing you can do after an accidental push is to panic and compound the problem with a hasty force push that creates confusion for your teammates. The revert approach is slower but leaves a clean, understandable history. Your teammates will see "Add feature / Revert 'Add feature'" and immediately understand what happened.

Mistakes in Git are almost always recoverable. The key is understanding what you're recovering from before you take action.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

How to Laugh at Yourself After a Huge Mistake

We’ve all been there: the code breaks, the email goes to the wrong person, or the deployment wipes out production. Learning to laugh at these moments can save your sanity and even make you a better professional.

Read more

The Real Cost of a Senior Backend Developer — Full-Time vs Contractor vs Async Remote

The offer letter number is the smallest part of what a backend hire actually costs. Here's what the full comparison looks like across three models.

Read more

Austin's Backend Developer Boom Is Cooling — What Startups Are Doing to Keep Shipping

The hiring market that made Austin feel like anything was possible has shifted. Here's how founders are staying lean without stalling out.

Read more

New Zealand's Tech Talent Pool Is Small. Async Remote Contractors Are How Startups Close the Gap

You've been looking for a senior backend engineer for three months. You've seen every relevant CV in Auckland twice. The pool isn't refreshing — it's the same twelve people.

Read more