← Git

Workflows & Best Practices

What is the difference between `git reset`, `git revert`, and `git checkout`?

Show answer — try answering out loud first

git reset moves HEAD to another commit and can modify staging and the working directory (it rewrites local history). git revert creates a new commit that undoes the changes of another one, without erasing history (safe for published work). git checkout moves HEAD between branches/commits or restores files (today split into switch and restore).

All three touch the repo's state, but in different ways:

  • git reset <commit>: moves the current branch to that commit. With --soft it keeps changes staged, --mixed (the default) leaves them unstaged, --hard deletes them. It rewrites history, so only locally.
  • git revert <commit>: it deletes nothing; it creates a new commit that is the inverse of the given commit. Since it doesn't rewrite history, it's the safe option for undoing something already shared.
  • git checkout: historically it did two things: switch branch/commit (move HEAD) and restore files. That's why Git split it into git switch (branches) and git restore (files), which are clearer.

Summary: reset for local history, revert for public history, checkout/switch/restore to navigate and restore.

# RESET: move HEAD backward (rewrites local history)
git reset --soft HEAD~1   # undo the commit, keep changes staged
git reset --mixed HEAD~1  # undo, changes unstaged (default)
git reset --hard HEAD~1   # undo and DELETE the changes (careful)

# REVERT: undo a published commit by creating an inverse one (safe)
git revert abc1234
# Creates a new commit that cancels out the changes of abc1234

# CHECKOUT (classic use) and its modern replacements:
git checkout otra-rama        # switch branch -> today: git switch otra-rama
git checkout -- archivo.txt   # discard changes -> today: git restore archivo.txt
git checkout abc1234          # go to a specific commit (detached HEAD)

Using git reset --hard on a shared branch (it rewrites history that others have). Confusing reset with revert: reset deletes/moves, revert adds an inverse commit. And with checkout, forgetting that you should now use switch for branches and restore for files, which make the intent much clearer.

"git reset moves HEAD to another commit and, depending on the mode, touches staging and the working directory; it rewrites history, so I only use it locally. git revert deletes nothing: it creates a new commit that undoes the changes of another one, which is why it's safe for already-published history. git checkout originally switched branches and also restored files; Git split it into switch for branches and restore for files, which are clearer. Mental rule: reset for local, revert for public, switch/restore to navigate."

Quick challenge

A commit with a bug is already on main and several teammates have already pulled. Do you use reset --hard or revert to undo it?

See answer

git revert. Since the commit is already published and others have it, reset --hard would rewrite the shared history and cause them divergences and conflicts. git revert creates a new commit that cancels out the changes of the buggy commit without erasing history, so everyone can pull without problems.