[!NOTE] “To err is human; to git reset is divine.”

We all make mistakes. You committed too early, you forgot to add a file, or you completely botched the feature. Git provides powerful tools to rewrite history and cover your tracks.

The Hardware Reality: What is a Reset?

When you run git reset, you aren’t actually “deleting” commits immediately. You are simply moving a pointer.

Go to your .git folder and look at .git/refs/heads/main. It contains a single string: the SHA-1 hash of the current commit.

cat .git/refs/heads/main
# Output: 3a1b2c...

When you run git reset HEAD~1, Git just overwrites that file with the parent’s hash. The old commit becomes “dangling” (orphaned) and is eventually cleaned up by Git’s garbage collector.

Amending the Last Commit

The simplest form of rewriting history is fixing the very last commit.

# You committed, but forgot to add 'config.json'
git add config.json
git commit --amend --no-edit

This replaces the previous commit with a new one (new SHA-1) that includes the extra file. The --no-edit flag keeps the original commit message. If you want to change the message:

git commit --amend -m "New commit message"

[!WARNING] Amending changes the commit hash. Do not amend commits you have already pushed to a shared repository!

The Three Modes of git reset

git reset is often misunderstood. It moves the HEAD pointer to a specific commit. But what happens to your changes depends on the “mode”.

Interactive Reset Visualizer

Use the simulator below to understand how --soft, --mixed (default), and --hard affect your repository.

Repository (History)
Commit A
Commit B
Commit C (HEAD)
Index (Staging)
Changes from C
Working Directory
Changes from C
Click a button to see what happens when you run `git reset HEAD~1`.

Detailed Breakdown

1. Soft Reset (--soft)

Moves HEAD back, but keeps your changes Staged.

  • Use case: You want to squash the last 3 commits into one manually. You reset HEAD~3, and now all changes are staged, ready for a single git commit.

2. Mixed Reset (--mixed)

Moves HEAD back, and keeps your changes in the Working Directory, but Unstaged.

  • Use case: You want to keep your work but rethink what you are committing.

3. Hard Reset (--hard)

Moves HEAD back and destroys all changes.

  • Use case: You completely broke everything and want to go back to a known good state.
  • Danger: Uncommitted changes are lost forever.

Reverting: The Safe Undo

If you have already pushed your changes, you should generally not use reset. Instead, use revert.

git revert HEAD

This creates a new commit that introduces the opposite changes of the target commit.

Visual Comparison: Reset vs Revert

Initial State A B C HEAD git reset HEAD~1 Result (History deleted) A B HEAD C git revert HEAD Result (New commit added) A B C D HEAD (Undo C)

Reset vs Revert vs Checkout

Command Modifies History? Safe for Public? Use Case
git reset Yes ❌ No Fixing local mistakes before pushing.
git revert No (Adds to it) ✅ Yes Undoing a bug pushed to production.
git checkout No ✅ Yes Viewing old code without changing history.

[!TIP] Pro Tip: If you did a git reset --hard by accident, you might still be able to save your work using Reflog (covered in the next chapter).