How to rewrite Git history without losing your work

I thought I had seen every way a repo could break, and then a junior dev walked into my office last Tuesday. He had merged a half finished experiment into the production branch, panicked, and tried to delete the .git folder to “start over.” If you know that cold drop in your stomach after a bad commit, keep reading. You can rewrite Git history without guessing, once you know where the undo button actually is.

Fourteen years of WordPress development taught me to treat Git as a time machine rather than a backup tool. Like any time machine, if you do not understand the mechanics you end up in a timeline where the site is down and your coffee is cold.

The three trees of Git

Before you rewrite Git history, you need to know where your code actually lives at any given moment. Git tracks three separate “trees”, or states:

  • The working directory: the actual files on your laptop.
  • The index, or staging area: the waiting room for your next commit.
  • The repository: the permanent snapshots, meaning the commits Git has recorded.

Nearly every undo operation is just moving data between those three areas. Once that clicks, you stop guessing and start debugging. For the wider workflow picture, here is my take on Pro Block Theme Development Workflows.

Undoing local mistakes with git reset

For a mistake that has not left your machine, git reset is the tool. It has three modes, and picking the wrong one is usually why a simple undo turns into a mess.

1. git reset –soft, the surgeon’s knife

Use --soft when you only want to un-commit. It moves the branch pointer back and leaves your changes staged in the index, which is exactly what you want for fixing a bad commit message or squashing a few small commits into one.

# Move back one commit, keep changes staged
git reset --soft HEAD~1

2. git reset –mixed, the default

This is the default mode. It undoes the commit and the staging, so your changes stay in your files but are no longer added to Git. I reach for it when I have staged too many files and want to be more selective.

3. git reset –hard, the nuclear option

This one wipes everything, matching your working directory and index to the previous commit. Caution: anything you have not committed is gone for good. I only run it when a local experiment has gone completely sideways.

How to rewrite Git history for pushed commits

One rule to keep: never reset commits you have already pushed to a shared server, because that breaks the history for everyone else on the team. Use git revert instead. It writes a new commit that does the exact opposite of the bad one.

# Revert the very last commit safely
git revert HEAD

The log gets noisier, but that is the grown up way to handle a mistake when other people work in the same repo. The official Git documentation covers the nuances of revert versus reset.

The “oh crap” button: git reflog

So you ran git reset --hard and deleted the wrong thing. With most tools that would be the end of it, but Git quietly logs every move your HEAD pointer makes. That log is the reflog.

# See everything you've done in the last 30 days
git reflog

You get a list of SHA-1 hashes. Find the one from right before you messed up and reset back to it. That has saved my skin more times than I care to admit.

If rewriting Git history is eating your dev hours, hand it to me. I have been wrestling with WordPress since the 4.x days, and I have seen about every broken merge and race condition there is.

Whiteboard before you type

The most useful tool in my kit is a piece of paper. Before you rewrite Git history, draw the current state and the state you want. If you cannot draw it, you do not understand it yet. Then take a breath, work out which of the three trees your changes are sitting in, and pick the command for that. Git forgives a lot once you stop treating it as a black box and start treating it as the filesystem snapshot engine it is.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.