[!NOTE] “To err is human; to
git resetis 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.
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 singlegit 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
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 --hardby accident, you might still be able to save your work using Reflog (covered in the next chapter).