Undoing Changes in Git: reset, checkout, restore

Summary:
Learn how to undo mistakes using different Git commands.


When working with Git, mistakes happen. You might commit changes you want to take back, modify the wrong file, or simply change your mind about a local edit. Fortunately, Git provides robust tools for "undoing" changes. In this article, we’ll dive into three fundamental commands for undoing work in Git: reset, checkout, and restore.

Table of Contents


Understanding the Git Three-Tree Architecture

Before undoing changes, it’s helpful to know where changes reside in Git's three main states:

  • Working Directory: Your local files with changes (edited, new, deleted)
  • Staging Area (Index): Files marked for inclusion on the next commit (git add)
  • Repository (HEAD/Commit History): All commits in the repository

Undoing changes can manipulate any of these three areas.


git reset

What it Does

git reset moves the current branch pointer and, optionally, modifies the staging area and working directory to match a specified commit. It is mainly used to undo commits or unstage files.

Common Forms

  • Soft Reset (--soft): Moves HEAD to the specified commit. Staging and working directory unchanged.
  • Mixed Reset (--mixed, default): Moves HEAD and updates the staging area. Working directory unchanged.
  • Hard Reset (--hard): Moves HEAD and updates both staging area and working directory to match the commit.

Examples

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

# Unstage files, keep changes in working directory
git reset HEAD <file>

# Completely discard all changes and commits after a certain commit
git reset --hard <commit>

Warning: --hard deletes your changes permanently unless committed elsewhere.


git checkout

What it Does

Historically, the git checkout command was used to switch branches and restore files. Since Git 2.23 (August 2019), its role has been split. However, you may still encounter it for the following actions:

  • Switch between branches.
  • Restore a file in your working directory from a commit.

Examples

# Switch to another branch
git checkout feature-branch

# Restore a file from the latest commit
git checkout HEAD -- README.md

# Restore a file from a specific commit
git checkout <commit> -- file.txt

Note: Today, git switch and git restore are recommended for these tasks (see below).


git restore

What it Does

Introduced in Git 2.23, git restore provides a clearer, focused interface for restoring file contents. It directly affects the working directory and the staging area.

Common Usage

  • From Latest Commit to Working Directory:

    # Discard local changes to a file
    git restore file.txt
    
  • Unstage File (Keep Changes in Working Directory):

    git restore --staged file.txt
    
  • Restore From a Specific Commit:

    git restore --source=<commit> file.txt
    

When to Use Each Command

Command Use case Caution
git reset Undo commits, unstage files --hard deletes changes permanently
git checkout Switch branches, restore files from commits Use git switch or git restore in modern Git
git restore Discard changes in files, unstage changes Only affects working directory or staging area

Common Scenarios and Examples

1. Revert Unstaged Local Changes

You edited a file but want the original content back.

git restore file.txt

2. Unstage a File

You ran git add, but want to unstage:

git restore --staged file.txt
# or
git reset HEAD file.txt

3. Undo Last Commit (Keep Changes in Working Directory)

You made a commit but realized you need to edit it:

git reset --soft HEAD~1

4. Undo Last Commit (Lose Changes)

Danger! This removes the commit and the changes themselves:

git reset --hard HEAD~1

5. Switch Branches

git switch develop
# or
git checkout develop

Summary Table

Task Command
Discard local file changes git restore file.txt
Unstage file (keep local changes) git restore --staged file.txt
Undo last commit, keep changes staged git reset --soft HEAD~1
Undo last commit, move changes to WD git reset --mixed HEAD~1
Undo last commit, remove all changes git reset --hard HEAD~1
Switch branches git switch <branch> / git checkout <branch>
Restore file from previous commit git restore --source=<commit> file.txt

Conclusion

Making mistakes in Git isn’t tragic—with the right commands, you can recover almost effortlessly. git reset, git checkout, and git restore are powerful tools for reverting unwanted changes. Just be cautious with commands that destroy data (reset --hard). With practice, you’ll master the art of undoing mistakes and keeping your project history tidy.


Further Resources: