Lesson 19 of 6820 min read

Undoing Changes: git restore, git checkout (Old Syntax), and git clean

Learn the modern and legacy ways to discard unwanted changes in Git — restoring tracked files and removing untracked ones safely.

Author: CodersNexus

Undoing Changes: git restore, git checkout (Old Syntax), and git clean

Mistakes and experiments are a normal part of software development, and Git provides several distinct commands for undoing unwanted changes depending on exactly what needs to be discarded: edits to a tracked file, or entirely untracked files cluttering your working directory. This lesson covers the modern `git restore` command, the older `git checkout` syntax it was designed to clarify, and `git clean` for removing untracked files.

Learning Objectives

  • Discard unstaged changes to a tracked file using git restore.
  • Understand the legacy git checkout -- <file> syntax and why git restore was introduced.
  • Preview and remove untracked files safely using git clean -n and git clean -f.
  • Choose the correct undo command based on whether a file is tracked, staged, or untracked.

Key Terms to Know Before Learning Undoing Changes

  • git restore: A modern command specifically for restoring working directory files to a previous state, or unstaging files, introduced to replace overloaded uses of git checkout.
  • git checkout -- <file>: The older, pre-2.23 syntax for discarding unstaged changes to a tracked file, restoring it to its last committed state.
  • git clean: A command that permanently deletes untracked files from the working directory.
  • Dry run: A preview mode (e.g., git clean -n) that shows what would be deleted without actually deleting anything.
  • -f (force) flag: Required by git clean to actually perform deletions, as a safety measure against accidental data loss.

How Undoing Changes Actually Works

Before Git 2.23 (released in 2019), the single `git checkout` command was heavily overloaded — used both for switching branches and for discarding changes to files, which was a frequent source of confusion and, occasionally, accidental data loss. Git introduced two new, more clearly scoped commands: `git switch` (for branches, covered in a later module) and `git restore` (for discarding or restoring file changes).

**To discard unstaged changes** in a tracked file — reverting it back to its last committed (or staged) state — the modern command is:

```
git restore app.js
```

This permanently discards any edits made to `app.js` since it was last staged or committed, restoring exactly that prior version. This is a destructive operation — there is no separate 'undo' for it, so it should be used deliberately, ideally after confirming with `git diff` (Module 1, Lesson 12) exactly what you're about to lose.

The equivalent **legacy syntax**, which you'll still frequently encounter in older tutorials, Stack Overflow answers, and some team conventions, is:

```
git checkout -- app.js
```

The `--` here is important — it separates the file path from anything that might otherwise be interpreted as a branch name, which was part of the ambiguity that led to `git restore` being introduced. Functionally, for this specific use case, both commands behave the same way.

**Untracked files** — files Git has never staged or committed, such as stray temporary files, build artifacts not covered by `.gitignore`, or abandoned experiments — are not touched by `git restore` or `git checkout`, since those commands only affect tracked content. To remove untracked files from your working directory, use `git clean`:

```
git clean -n # dry run: PREVIEW what would be deleted, without deleting anything
git clean -f # actually delete untracked files (force flag required)
git clean -fd # also remove untracked DIRECTORIES, not just files
```

Git deliberately requires the `-f` (force) flag before `git clean` will delete anything, as a safety measure — running it without `-f` (or without `-n` for a dry run) typically does nothing and shows a warning. Always run `git clean -n` first to review exactly what will be deleted, since this operation is permanent and cannot be undone through Git (the files are not staged, committed, or otherwise recoverable from history).

In summary: use `git restore <file>` (or the older `git checkout -- <file>`) to discard changes to files Git already tracks, and use `git clean` to remove files Git has never tracked at all.

Undoing Changes: Visual Walkthrough

Draw a decision tree. Start: 'I want to undo something in my working directory'. First branch: 'Is the file already tracked by Git?' → Yes path leads to 'git restore <file> (or legacy: git checkout -- <file>) — discards unstaged edits, restoring last committed/staged version'. No path (untracked file) leads to 'git clean -n to preview, then git clean -f to permanently delete untracked files'.

Undoing Changes: Quick Reference Table

SituationCommandEffect
Discard unstaged edits to a tracked file (modern)git restore <file>Restores file to last staged/committed version
Discard unstaged edits to a tracked file (legacy)git checkout -- <file>Same effect as git restore, older syntax
Preview untracked files that would be deletedgit clean -nDry run — shows what would be removed, deletes nothing
Permanently delete untracked filesgit clean -fActually deletes untracked files (irreversible)
Permanently delete untracked files AND directoriesgit clean -fdAlso removes untracked folders, not just files

Undoing Changes: Command Syntax and Examples

# Discard unstaged changes to a tracked file (modern syntax)
git restore app.js

# Equivalent legacy syntax
git checkout -- app.js

# ALWAYS preview before deleting untracked files
git clean -n
# Example output:
# Would remove debug-notes.txt
# Would remove temp/

# Actually delete untracked files (force flag required)
git clean -f

# Also remove untracked directories
git clean -fd

Breaking Down the Undoing Changes Example

`git restore app.js` and the older `git checkout -- app.js` both discard any unstaged edits to that tracked file, reverting it to its last staged or committed content — a destructive but scoped action limited to that one file. `git clean -n` is shown as a mandatory first step before ever deleting untracked files: it lists exactly what would be removed (`debug-notes.txt` and the `temp/` directory in this example) without touching anything yet. Only after confirming that preview is safe should `git clean -f` (and `-fd` if directories are also involved) actually be run, since this operation cannot be undone.

How Undoing Changes Is Used on Real Engineering Teams

  • Developers commonly run git restore <file> after an experimental change doesn't work out, cleanly reverting just that file without affecting any other work in progress.
  • CI/CD build scripts frequently run git clean -fdx (an extended variant also removing ignored files) at the start of a build to guarantee a completely pristine working directory before compiling, avoiding stale artifacts from a previous run.
  • Senior engineers strongly emphasize always running git clean -n before -f in onboarding documentation, since accidental permanent deletion of untracked work (like an unstaged prototype file) is a classic, painful mistake for beginners.
  • Legacy codebases and older internal documentation at many companies still reference git checkout -- <file> syntax, making familiarity with both old and new commands valuable when working across different teams or tutorials.

Undoing Changes Interview Questions and Answers

Q1. How do you discard unstaged changes to a specific file in Git?

Use git restore <file> (the modern syntax) or the older equivalent, git checkout -- <file>. Both discard any edits made to that file since it was last staged or committed, restoring it to that prior state.

Q2. Why was git restore introduced when git checkout already existed?

git checkout had become overloaded, used both for switching branches and for discarding file changes, which caused confusion and occasional accidental mistakes. Git 2.23 introduced git restore (for file changes) and git switch (for branches) to give each purpose its own clearly scoped, less error-prone command.

Q3. How do you remove untracked files from your working directory, and what safety step should you always take first?

Use git clean -f to delete untracked files (git clean -fd to also remove untracked directories). Before running this, always run git clean -n first, which performs a dry run showing exactly what would be deleted without actually removing anything, since the deletion itself is permanent and unrecoverable through Git.

Undoing Changes Quiz: Test Your Understanding

1. Which modern command discards unstaged changes to a tracked file, restoring it to its last committed version?

  1. git clean
  2. git restore
  3. git remove
  4. git undo

Answer: B. git restore

Explanation: git restore is the modern, clearly scoped command for discarding working directory changes to tracked files, introduced to replace an overloaded use of git checkout.

2. What is the purpose of running git clean -n before git clean -f?

  1. It automatically fixes merge conflicts
  2. It performs a dry run, previewing what would be deleted without actually deleting anything
  3. It stages untracked files instead of deleting them
  4. It reverts the last commit

Answer: B. It performs a dry run, previewing what would be deleted without actually deleting anything

Explanation: The -n flag runs git clean in preview mode, listing exactly what untracked files/directories would be removed, letting you confirm before running the irreversible -f (force) deletion.

3. Does git restore or git clean affect untracked files?

  1. Both affect untracked files
  2. Only git restore affects untracked files
  3. Only git clean affects untracked files
  4. Neither command can affect any files

Answer: C. Only git clean affects untracked files

Explanation: git restore only affects files Git already tracks (reverting unstaged edits). Untracked files are untouched by restore or checkout, and require git clean specifically to remove.

Undoing Changes: Common Mistakes Beginners Make

  • Running git restore or git checkout -- <file> without first checking git diff, permanently losing unstaged work that wasn't actually meant to be discarded.
  • Running git clean -f directly without first previewing with git clean -n, accidentally and permanently deleting important untracked files.
  • Forgetting that git clean -f alone does not remove untracked directories — the -d flag is needed for that (git clean -fd).
  • Assuming git restore can recover a file that was deleted from disk entirely and never tracked — restore only works on files Git already knows about.

Undoing Changes: Exam-Ready Quick Notes

  • git restore <file> (modern) or git checkout -- <file> (legacy): discard unstaged changes to a tracked file.
  • git clean removes untracked files; requires -f (force) to actually delete, -d to also remove directories.
  • Always run git clean -n (dry run) before git clean -f to preview what will be permanently deleted.
  • Both restore/checkout discards and clean deletions are irreversible through Git — use with caution.

Undoing Changes: Key Takeaways

  • git restore (or the legacy git checkout -- <file>) discards unstaged edits to tracked files, reverting to the last saved version.
  • git clean is the separate tool needed for removing untracked files, which restore and checkout never touch.
  • Both classes of undo are permanent — always preview with git diff or git clean -n before executing them.

Frequently Asked Questions About Undoing Changes

Q1. How do I undo changes I made to a file but haven't staged yet?

Run git restore <file>, which discards those unstaged edits and reverts the file to its last staged or committed version. This is permanent, so it's a good idea to check git diff first to confirm you're not losing something important.

Q2. What is the difference between git restore and the older git checkout -- <file>?

They accomplish the same thing for this specific purpose — discarding unstaged changes to a tracked file. git restore is the newer, more clearly scoped command introduced in Git 2.23, since git checkout was previously overloaded with both branch-switching and file-restoring responsibilities.

Q3. How do I delete files that Git isn't tracking at all?

Use git clean. First run git clean -n to preview exactly what untracked files would be removed, then run git clean -f to actually delete them (add -d as well, making it git clean -fd, if you also want untracked directories removed).

Q4. Why does git clean require a -f flag to actually delete anything?

It's a deliberate safety measure. Because deleting untracked files is permanent and cannot be undone through Git, requiring an explicit force flag helps prevent accidental data loss from running the command without fully understanding its effect.

Q5. Can I recover a file after running git restore or git clean?

Not through Git. Restoring a tracked file permanently discards unstaged edits with no separate undo, and git clean permanently deletes untracked files that were never part of Git's history. Always double-check with git diff or git clean -n before proceeding.

Summary

Git provides distinct commands depending on what needs to be undone. `git restore <file>` (the modern replacement for the older `git checkout -- <file>` syntax) discards unstaged edits to a tracked file, reverting it to its last staged or committed state. Neither command touches untracked files — for those, `git clean` is used, requiring the `-f` (force) flag to actually delete files and `-d` to also remove untracked directories. Because both operations are permanent and unrecoverable through Git, it's essential to review changes with `git diff` before restoring, and always run `git clean -n` (a dry run) before `git clean -f` to confirm exactly what will be deleted.

Frequently Asked Questions

Run git restore <file>, which discards those unstaged edits and reverts the file to its last staged or committed version. This is permanent, so it's a good idea to check git diff first to confirm you're not losing something important.

They accomplish the same thing for this specific purpose — discarding unstaged changes to a tracked file. git restore is the newer, more clearly scoped command introduced in Git 2.23, since git checkout was previously overloaded with both branch-switching and file-restoring responsibilities.

Use git clean. First run git clean -n to preview exactly what untracked files would be removed, then run git clean -f to actually delete them (add -d as well, making it git clean -fd, if you also want untracked directories removed).

It's a deliberate safety measure. Because deleting untracked files is permanent and cannot be undone through Git, requiring an explicit force flag helps prevent accidental data loss from running the command without fully understanding its effect.

Not through Git. Restoring a tracked file permanently discards unstaged edits with no separate undo, and git clean permanently deletes untracked files that were never part of Git's history. Always double-check with git diff or git clean -n before proceeding.