How do I discard unstaged changes in Git that are in my working copy but not in the index?
The most straightforward way to discard unstaged changes in your working copy is to use git restore <file> for specific files or git restore . for all files, which was introduced in Git 2.23 as a more explicit replacement for the older git checkout -- <file> syntax. These commands restore files in your working directory to match the version in your index (staging area) or last commit, effectively removing any unstaged modifications without affecting your staged changes or commit history.
Contents
- Understanding Git’s Working Directory and Index
- Using
git restoreto Discard Unstaged Changes - Alternative Commands for Discarding Unstaged Changes
- Best Practices and Safety Considerations
- Troubleshooting Common Issues
Understanding Git’s Working Directory and Index
In Git terminology, the working directory (or working copy) is where you actively make changes to your files. Any modifications you make here are not tracked until you stage them using git add. The staging area (also known as the “index”) is where changes you intend to include in your next commit are temporarily stored before you commit them.
When you run git status, you’ll see different categories of changes:
- Changes not staged for commit: These are modifications in your working directory that haven’t been added to the staging area
- Changes to be committed: These are staged changes ready for your next commit
- Untracked files: These are new files that Git isn’t tracking yet
For discarding unstaged changes, you’ll want to focus on the “Changes not staged for commit” section, as these are the modifications in your working copy that aren’t in the index.
Key Insight: Unstaged changes exist only in your working directory and haven’t been committed or staged. This makes them safe to discard without affecting your commit history.
Using git restore to Discard Unstaged Changes
For Specific Files
The modern approach to discard unstaged changes in specific files is using git restore:
git restore <file1> <file2> <file3>
For example, if README.md and src/main.js have unstaged changes:
git restore README.md src/main.js
This command will restore both files to match their versions in the index (staging area) or the last commit, whichever is more recent.
For All Files
To discard unstaged changes in all tracked files across your entire repository:
git restore .
According to the official Git documentation, “If you run the latter from the root of the repository, it will discard unstaged changes in all tracked files in the project.”
Understanding the git restore Command
The git restore command was introduced in July 2019 and released in Git version 2.23 as part of a split of the git checkout command into more specific commands:
git restorefor file operationsgit switchfor branch operations
As Stack Overflow explains, “git restore was introduced in July 2019 and released in version 2.23 as part of a split of the git checkout command into git restore for files and git switch for branches.”
Alternative Commands for Discarding Unstaged Changes
Legacy git checkout Syntax
Before Git 2.23, the standard way to discard unstaged changes was:
git checkout -- <file>
For all files:
git checkout .
This syntax still works but is considered legacy. The Git documentation shows that git status still suggests this older syntax: “(use “git checkout –
git reset Commands
While primarily used for manipulating the staging area and commit history, git reset can also help with discarding changes:
For Specific Files (without affecting staging):
git reset HEAD <file>
This unstages a file but doesn’t discard the working directory changes. You’d then need to restore the working directory separately.
For All Changes (including staged):
git reset --hard HEAD
This command will discard both staged and unstaged changes and reset your working directory to match your last commit. Use with caution as this is destructive.
As Better Stack Community warns, “Commands like git restore ., git reset --hard HEAD, and git clean -fd will permanently delete changes and files. Use these commands with caution.”
Comparison of Methods
| Command | What it Affects | Safety | Git Version |
|---|---|---|---|
git restore <file> |
Working directory only | Safe | 2.23+ |
git checkout -- <file> |
Working directory only | Safe | All versions |
git restore . |
All working directory changes | Safe | 2.23+ |
git reset --hard HEAD |
Working directory + staging + HEAD | Destructive | All versions |
Best Practices and Safety Considerations
Before Discarding Changes
- Review your changes: Always run
git difforgit diff --stagedto see exactly what changes you’re about to discard - Consider stashing: Use
git stashto temporarily save your work if you might need it later - Check your status: Run
git statusto confirm you’re targeting the right files
Safety Tips
- Start with specific files: Always test on individual files before using
git restore . - Use version control: Make sure you have committed important work before discarding changes
- Backup critical changes: For important uncommitted work, consider copying files to a safe location before restoration
When to Use Each Method
- Use
git restore <file>: When you want to discard specific unstaged changes in the working directory - Use
git restore .: When you want to discard all unstaged changes across the entire repository - Use
git reset --hard HEAD: Only when you want to discard all changes (both staged and unstaged) and reset to your last commit
Troubleshooting Common Issues
“Untracked Files” vs “Unstaged Changes”
Remember that git restore only affects tracked files. To remove untracked files (new files not yet added to Git), you need:
git clean -fd
Use git clean -n first to see what would be deleted without actually deleting it.
Mixed Staged and Unstaged Changes
If you have both staged and unstaged changes in the same file, and you want to keep the staged changes but discard the unstaged ones:
git restore <file> # This will discard unstaged changes
git add <file> # Keep the staged changes
Accidental Restoration
If you accidentally restore files, you can often recover them from your Git history:
git checkout HEAD -- <file> # Restore from last commit
Or for more recent changes:
git reflog # Find the commit before restoration
git checkout <commit-hash> -- <file>
File Permissions Issues
On some systems, you might encounter permission issues when using git restore. In such cases:
git checkout HEAD -- <file> # Alternative approach
Conclusion
Discarding unstaged changes in Git is a common operation that can be performed safely using several commands. The modern git restore command is the recommended approach for Git 2.23 and later, offering clear and explicit functionality for restoring working directory changes. Always review your changes before discarding them, and consider using git stash to preserve important work temporarily. Remember that git restore only affects tracked files in your working directory and won’t remove untracked files or affect your staging area or commit history.
For most use cases, git restore <file> or git restore . will be your go-to commands, providing a safe and straightforward way to clean up your working directory when needed.
Sources
- Stack Overflow - How do I discard unstaged changes in Git?
- Official Git Documentation - Git Basics: Undoing Things
- W3Docs - How to Discard Unstaged Changes in Git
- Graphite.dev - How to discard unstaged changes in Git
- Baeldung on Ops - How to Discard Unstaged Changes in Git
- The Serverside - How to discard local changes in Git
- Better Stack Community - Git Undo All Uncommitted or Unsaved Changes
- Reddit r/git - Undo unstaged file
- Sentry - Discard unstaged changes in Git
- DesignGurus.io - How do I discard unstaged changes in Git?