Profile    Mohammed Shiroz Status   Loading  
Logo
Share This
Back to blog
Filter by:
Tags
//Article title

Git Mistakes and How to Undo Them (Without Making Things Worse)

About Post

There's a specific kind of silence that follows a Git command you regret. You pressed Enter, the terminal printed something short and final, and your stomach dropped before your brain caught up.

Here's the good news: Git is very hard to truly break. Almost everything you've committed can be recovered, and most mistakes have a clean, one- or two-command fix. The danger isn't the mistake. It's the panicked second command typed to fix the first one.

So here's a calm rescue guide. Find your situation, read the warning, then type.

First question: has it been pushed?

Almost every fix depends on this. The rule is simple:

  • Not pushed yet: it's your private history. Rewrite it freely with amend, reset and rebase.
  • Pushed to a shared branch: other people may have built on it. Don't rewrite it; add a new commit that undoes it with revert.

Keep that in mind for everything below.

"I forgot a file" or "the commit message has a typo"

Not pushed? Amend the last commit:

git add app/Models/Lease.php
git commit --amend --no-edit        # add the file, keep the message
git commit --amend -m "Fix lease renewal date calculation"   # or fix the message

--amend replaces the last commit with a new one. That's fine locally, but if you already pushed, amending means you'll need a force push, which brings its own rules (see below).

"I committed to main instead of my feature branch"

Classic. Not pushed yet? Create the branch where you are, then move main back:

git branch feature/lease-renewals   # new branch keeps your commit
git reset --hard HEAD~1             # move main back one commit
git switch feature/lease-renewals   # carry on working here

If you made three commits by mistake, use HEAD~3. And if the feature branch already exists, switch to it and git cherry-pick <sha> the commit across before resetting main.

Warning: --hard also throws away any uncommitted changes. Run git status first, and git stash if anything is there.

"I want to undo my last commit": reset, three ways

git reset moves your branch back. The flag decides what happens to the changes from the commits you're undoing:

CommandThe commitIts changesUse when
git reset --soft HEAD~1UndoneKept, still stagedYou want to recommit differently
git reset HEAD~1 (mixed)UndoneKept, unstagedYou want to re-pick which files go in
git reset --hard HEAD~1UndoneThrown awayYou really want it gone

When in doubt, use --soft. You can always throw changes away later; you can't easily get uncommitted work back.

"I pushed a bad commit to a shared branch"

Don't reset. Revert. git revert creates a new commit that does the exact opposite of the bad one, so history only moves forward and nobody else's clone breaks:

git revert 4f9c2ab
git push

Reverting a merge commit needs one extra flag to say which parent is the "main line", usually the first: git revert -m 1 <merge-sha>. One gotcha worth knowing: if you later merge that same branch again, the reverted changes won't come back automatically, because Git thinks they're already merged. You'd need to revert the revert.

"I lost commits": reflog to the rescue

You did a reset --hard to the wrong place. A rebase went sideways. You deleted a branch that wasn't merged. It feels like the work is gone. It almost certainly isn't.

Git keeps a local diary of everywhere HEAD has pointed, called the reflog:

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# 9e8f7a6 HEAD@{1}: commit: Add renewal reminders
# ...

git branch rescue 9e8f7a6     # put a branch on the lost commit

Creating a branch is the safest move: it makes the lost commit reachable again without changing anything else. Then inspect it and merge or reset as you like.

Two more lifelines. When you delete a branch, Git prints its last commit (Deleted branch x (was 1a2b3c4)), so git branch x 1a2b3c4 brings it back. And right after a bad rebase, reset or merge, ORIG_HEAD points to where you were before: git reset --hard ORIG_HEAD.

The reflog is local to your machine and old entries do expire eventually (by default after months, not minutes), so you have plenty of time, but not forever.

The rule that makes all of this work: committed work is almost never lost; uncommitted work easily is. reset --hard, git restore and git clean on uncommitted changes have no undo. Commit early, even as "wip", and tidy up before you push.

"I need to force push": do it safely

After amending or rebasing a branch you'd already pushed, a normal push is rejected. A plain git push --force overwrites the remote branch with yours, including any commits a colleague pushed in the meantime, which are then gone from the branch.

Use the safer version:

git push --force-with-lease

It refuses to push if the remote branch has changed since you last fetched it. One subtlety: if your editor fetches in the background, your "last fetch" may include commits you've never actually looked at. Adding --force-if-includes (Git 2.30 and later) guards against that too.

And the simplest rule: only force push to your own branches, never to main or a shared branch. Most teams protect main on GitHub or GitLab so it can't happen by accident.

"I committed a secret"

The one where Git isn't the main fix. If an API key or password was pushed, assume it's been seen: rotate it first, immediately. Rewriting history afterwards (with a tool like git filter-repo) is cleanup, not a fix, because the old commit can already live in other clones, forks and CI logs.

Not pushed yet? Amend or reset it out, add the file to .gitignore, and you got lucky.

Smaller oops, quick fixes

  • Staged the wrong file: git restore --staged path/to/file.
  • Merge full of conflicts you're not ready for: git merge --abort.
  • Rebase in progress and it's a mess: git rebase --abort.
  • Not sure what you're about to lose: git status and git log --oneline -5 before any reset.

The rescue checklist

  1. Stop. Don't type the second command in a panic.
  2. Ask: pushed or not? Private history can be rewritten; shared history gets reverted.
  3. Lost something? git reflog, then put a branch on it.
  4. Force push only with --force-with-lease, only on your own branch.
  5. Commit early. Committed work is safe work.

What's the Git command that has given you that stomach-drop moment? And which one rescued you?

Comments (0)
Leave your review

Thanks for your valuable comments. Your comments has been updated and appreciate your getting in touch...

01. About Shiroz

Mohammed Shiroz

Hi, I'm Mohammed Shiroz, a software engineer and AI enthusiast from Sri Lanka who turns ideas into intelligent, real-world solutions. With over 9 years of hands-on experience, I currently lead real estate ERP development at Kate Group, a...

03.My Projects

04. Categories

Ready To order Your Project ?

Get in Touch
Close