Back to Blog
GitJuly 6, 20265 min read

How to Git Undo Changes: A Practical Guide for Developers

Master how to git undo changes safely. Learn the difference between git restore vs checkout, when to use git reset hard, and how to undo git commits.

gitversion controlsoftware engineeringterminaldeveloper toolsgit workflow

We’ve all been there: you make a series of changes, realize you’ve gone down the wrong path, and just want to get back to a clean state. Whether you’re trying to revert a single file or wipe out an entire afternoon of work, knowing how to git undo changes is a fundamental skill that saves hours of frustration.

I remember early in my career, I accidentally committed a secret key to a public repository. The panic was real. I spent about two days learning exactly how Git handles state transitions, and that experience taught me that Git isn't trying to be difficult—it’s just highly specific about where your code lives.

Understanding the Git State Machine

To fix mistakes, you have to know where the change currently sits. Is it just a modified file? Is it staged in the index? Or is it already sitting in your local commit history?

If you are confused about the differences, it helps to visualize the flow:

  1. Working Directory: Where you edit files.
  2. Staging Area (Index): Where you prepare snapshots via git add.
  3. Local Repository: Where your commits live.

How to Undo Unstaged and Staged Changes

If you haven't committed yet, you're in the "safe zone." You can discard changes without worrying about losing history.

For unstaged files, git restore is your best friend. It was introduced in Git 2.23 to simplify the confusing overlap between older commands.

Bash
# Discard changes in a specific file
git restore filename.js

# Discard all changes in the current directory
git restore .

If you’ve already staged the file with git add, you need to "unstage" it first. You can use git restore --staged <file> to move it back to the working directory without losing your edits.

People often ask about git restore vs checkout. Historically, git checkout did everything: switched branches, restored files, and moved HEAD. It was overloaded and dangerous. Today, stick to git restore for files and git switch for branches. If you need to revert a file to a previous version from a specific commit, git checkout <commit> -- <file> is still the standard, but use it carefully.

How to Undo Git Commit

Once you’ve made a commit, the stakes go up. You aren't just changing files anymore; you are changing history.

If you just need to fix a typo in your last commit message or add a forgotten file, the easiest path is:

Bash
# Add your missed file
git add forgotten_file.js

# Update the last commit without creating a new one
git commit --amend --no-edit

However, if you need to completely remove the last commit, you have a few options. I covered the nuance of this in my previous post on Git Reset vs Revert: How to Safely Undo Commits.

If you're working locally and haven't pushed to a shared remote, git reset --hard is the "nuclear option." It forces your branch back to a previous commit and deletes everything in between.

Bash
# WARNING: This deletes all uncommitted work!
git reset --hard HEAD~1

Be extremely careful with --hard. If you have uncommitted work you care about, use git stash first to save your current state to a temporary stack.

Comparison of Undo Strategies

ScenarioCommandRisk Level
Discard unstaged changesgit restore <file>Low
Unstage a filegit restore --staged <file>Low
Fix last commit messagegit commit --amendMedium
Remove last local commitgit reset --hard HEAD~1High

When Things Get Complicated

Sometimes you end up in a "detached HEAD" state, which feels like you've fallen off the map. If you've been experimenting with resets and rebases, check out Git Detached HEAD: How to Recover Lost Commits Safely to ensure you don't lose your work.

If you've pushed your changes to a shared branch, never use git reset --hard. You will break the history for everyone else on your team. Instead, use git revert, which creates a new commit that is the exact inverse of the bad one. It keeps the history intact and safe for your colleagues.

FAQ

Q: Can I undo a git reset --hard? A: Yes, usually. Git keeps a log of your movements called the reflog. Run git reflog to see your history, find the commit hash before your hard reset, and use git reset --hard <hash> to jump back to it.

Q: What is the difference between git reset and git revert? A: git reset moves the branch pointer backward, effectively erasing history. git revert adds a new commit that undoes the changes of a previous one, preserving the history. Always use revert on shared branches.

Q: How do I undo a git add? A: Use git restore --staged <file>. This takes the file out of the staging area but keeps your changes intact in your working directory.

Ultimately, the best way to avoid needing to undo complex operations is to keep your commits small and atomic. When you make mistakes—and you will—remember that the git reflog is your safety net. It’s saved me more times than I care to admit. Next time, I might look into automating some of these checks with custom scripts, perhaps even utilizing tools similar to those discussed in my eBPF-based File Access Auditing: Track Config Changes with bpftrace write-up, though for now, manual vigilance remains my primary defense.

Similar Posts