Skip to content
Home
Git Revert vs Reset: Undoing Changes the Right Way

Git Revert vs Reset: Undoing Changes the Right Way

Git Git 8 min read 1502 words Beginner ExcellentWiki Editorial Team

Git gives you several ways to undo changes, but they are not interchangeable. Using the wrong one — especially on shared branches — can delete teammates’ work, rewrite shared history, and create merge nightmares. Understanding the difference between git revert and git reset is essential for every developer.

The Core Difference

git revertgit reset
HistoryPreserves itRewrites it
SafetySafe on shared branchesDangerous on shared branches
OperationCreates a new commit that undoes a previous oneMoves the branch pointer backward
ResultAdds to commit historyRemoves commits from history
RecoveryTarget commit still exists in historyHarder to recover (use reflog)

The golden rule: use revert on public/shared branches, reset on private/local branches only.

Git Revert: The Safe Undo

git revert creates a new commit that inverses the changes from a target commit. The original commit stays in history, and a new “revert commit” is added on top.

# Revert a single commit
git revert HEAD

# Revert a specific commit by hash
git revert 9fceb02

# Revert multiple commits (creates one revert per commit)
git revert HEAD~3..HEAD

# Revert without auto-committing (edit the message)
git revert -n 9fceb02
git commit -m "Revert: feature X was causing database errors"

Revert in Practice

# Scenario: Commit 9fceb02 introduced a bug on main
git checkout main
git pull

# Create a revert commit
git revert 9fceb02

# Write a clear message:
# "Revert: Add user avatar upload
#  This caused a memory leak on large files. Reverting until we add size limits."

git push origin main

The revert commit is pushed like any other commit. Teammates pull and get the fix automatically — no force push, no history rewrite, no confusion. The original commit remains in the log for audit purposes, and it can be re-reverted (re-applied) later once the underlying issue is fixed.

Reverting a Merge Commit

Merge commits have two parents. Git needs to know which parent’s history to keep:

# Revert a merge commit (use -m 1 to keep the mainline)
git revert -m 1 <merge-commit-hash>

The -m 1 flag tells Git to keep the contents of the first parent (the branch you were on when you merged) and undo the changes from the second parent (the feature branch that was merged in). If you omit -m, Git will refuse to revert the merge because it does not know which parent to follow.

Git Reset: The Powerful Undo

git reset moves the current branch pointer backward, effectively removing commits from the branch history. It comes in three modes:

Soft Reset

# Move HEAD back but keep all changes staged
git reset --soft HEAD~1

Changes from the removed commit are moved to the staging area. Your working directory is unchanged. Use this when you committed too early and want to refine the commit.

Mixed Reset (Default)

# Move HEAD back, unstage changes but keep them in working directory
git reset HEAD~1
git reset --mixed HEAD~1  # explicit

Changes are moved from the staging area back to the working directory. Your files are untouched, but they become unstaged. This is useful when you staged files that should not have been in the commit.

Hard Reset

# DANGER: Move HEAD back and discard all changes
git reset --hard HEAD~1

# Reset to a specific commit (discarding everything after it)
git reset --hard 9fceb02

This is the most dangerous mode. It discards all changes in both the staging area and working directory. Files are permanently deleted (subject to reflog recovery). Never use this on a shared branch.

Reset a Specific File

# Unstage a file (keep working directory changes)
git reset HEAD -- filename.txt

# Discard all local changes to a file
git checkout -- filename.txt
# or
git restore filename.txt

Safe Recovery Workflows

Fix a Private Commit

# You committed to a local branch but the message is wrong
git commit --amend -m "Better commit message"

# You committed to local branch but forgot a file
git add forgotten-file.js
git commit --amend --no-edit

# You committed and want to split into two commits
git reset HEAD~1        # unstage everything
git add file1.js
git commit -m "Feature part 1"
git add file2.js
git commit -m "Feature part 2"

Undo a Public Commit (Safe)

# Wrong! This rewrites public history
git reset --hard HEAD~1
git push --force

# Right! This creates a revert commit
git revert HEAD
git push

Recover from a Hard Reset

# You ran git reset --hard HEAD~1 accidentally

# Find the lost commit
git reflog
# Output: 9fceb02 HEAD@{0}: reset: moving to HEAD~1
#         1a2b3c4 HEAD@{1}: commit: Important work

# Recover it
git reset --hard 1a2b3c4
# or create a branch at that commit
git branch recover-stuff 1a2b3c4

The reflog records every movement of HEAD, including resets. Commits are not immediately garbage collected — they remain in the object database for ~30 days (default GC window). The reflog is local and not pushed to remote, so recovery is only possible on the machine where the reset happened.

When to Use Each

Use git revert when:

- The commit has been pushed to a shared branch
- Other developers may have pulled your changes
- You want to keep a complete audit trail
- You need to undo a merge commit
- You are working on main or a shared feature branch

Use git reset when:

- The commit exists only in your local repository
- You have not pushed the commit yet
- You want to squash multiple commits before pushing
- You accidentally committed to the wrong branch
- You need to clean up your local commit history

How Git’s Object Model Affects Undo Operations

Understanding why revert and reset behave differently requires knowing Git’s object model. Commits in Git are immutable — once created, a commit’s content and metadata cannot change. Reset works by moving the branch pointer to a different commit, effectively abandoning the old commits from the branch’s perspective. Revert works by creating a new commit whose content is the inverse of the target commit, leaving the original commits intact.

This immutability is why recoverability differs between the two operations. With revert, the original commit is still reachable through the commit graph — you can always find it and undo the revert. With reset –hard, the abandoned commits become unreachable from any branch and will eventually be garbage collected, though the reflog provides a temporary safety net.

Cheat Sheet

# Undo last commit (keep changes)
git reset --soft HEAD~1

# Undo last commit (unstage changes)
git reset HEAD~1

# Undo last commit (discard changes) — local only!
git reset --hard HEAD~1

# Undo a pushed commit safely
git revert HEAD

# Undo a merge commit
git revert -m 1 <merge-hash>

# Unstage a file
git reset HEAD -- file.txt

# Discard local changes to a file
git restore file.txt

# Find lost commits after hard reset
git reflog

Common Mistakes

  1. Using reset on a shared branch — This is the most dangerous mistake. Always use revert for commits that have been pushed.
  2. Confusing –soft and –hard--soft keeps changes staged, --hard discards everything. If unsure, use --mixed (the default) which unstages but keeps files.
  3. Forgetting to check the remote — Before resetting, confirm that no one else has based work on the commits you are removing. git branch -r --contains <commit> shows remote branches that include a commit.
  4. Not using reflog after accidental hard reset — The reflog is your best recovery tool. Run git reflog immediately after an accidental reset before garbage collection runs.

Related: Learn git stash and git merge vs rebase.

FAQ

Q: What is the difference between git revert and git reset --hard? A: git revert creates a new commit that undoes changes without deleting history. git reset --hard moves the branch pointer backward and discards all changes. Revert is safe on shared branches; reset is not.

Q: Can I undo a revert? A: Yes. Since revert creates a normal commit, you can revert the revert: git revert <revert-commit-hash> reapplies the original changes.

Q: How long do I have to recover from a hard reset? A: Git’s garbage collection runs periodically, typically keeping unreachable objects for 30 days (90 for reachable reflog entries). Run git reflog immediately after an accidental reset.

Q: What does git revert -m 1 mean? A: It tells Git which parent to follow when reverting a merge commit. -m 1 keeps the mainline (the branch you were on when merging) and discards the changes from the merged branch.

Q: Is git restore the same as git reset for files? A: git restore is a newer, more intuitive command for discarding changes to files. git restore file.txt is equivalent to git checkout -- file.txt but clearer in intent.

Q: Can I use reset on a branch that has been pushed but not shared? A: If you are the only person working on the branch and no one else has pulled it, reset + force push is acceptable. But --force-with-lease should always be used instead of --force.

Section: Git 1502 words 8 min read Beginner 756 articles in section Report inaccuracy Back to top