How to Undo a Git Add: Unstaging Files Before You Commit
Running git add is one of the most routine actions in a Git workflow — but it's also one of the easiest to do too early, too broadly, or on the wrong files. The good news: staging a file doesn't lock you in. Git gives you clear, reliable ways to reverse a git add before the changes ever land in a commit.
What "Git Add" Actually Does
When you run git add, you're not saving your work permanently — you're moving changes from your working directory into the staging area (also called the index). Think of the staging area as a draft queue: files sit there waiting until you run git commit, at which point they become part of your project's permanent history.
Until that commit happens, the staging area is entirely reversible. Undoing a git add simply means moving a file back out of that queue — your actual file contents aren't touched.
The Main Commands for Unstaging Files
git restore --staged (Git 2.23 and later)
This is the current recommended approach for most users. It's explicit, readable, and purpose-built for this exact task.
git restore --staged filename.txt To unstage everything you've added in one go:
git restore --staged . The --staged flag tells Git to only affect the staging area. Your working directory files stay exactly as they are — no content is lost or modified.
git reset HEAD (older but widely supported)
Before Git 2.23, git reset HEAD was the standard way to unstage files. It still works in every version of Git and appears constantly in documentation, tutorials, and Stack Overflow answers, so it's worth knowing.
git reset HEAD filename.txt To unstage everything:
git reset HEAD . Functionally, for the purpose of unstaging, git reset HEAD and git restore --staged produce the same result. The difference is mostly in clarity — git restore is harder to misread.
⚠️ Be careful with git reset flags. Using git reset --hard is a different command entirely and will overwrite your working directory changes. When unstaging, use git reset with no flags, or stick with git restore --staged.
Unstaging a Specific File vs. Everything
| Goal | Command |
|---|---|
| Unstage one file | git restore --staged filename.txt |
| Unstage multiple files | git restore --staged file1.txt file2.txt |
| Unstage all staged files | git restore --staged . |
| Unstage using older syntax | git reset HEAD filename.txt |
How to Check What's Staged Before You Unstage
Before running any unstage command, git status gives you a clear picture of what's currently staged versus what's only modified in your working directory.
git status Files listed under "Changes to be committed" are staged. Files under "Changes not staged for commit" are modified but not yet added. This distinction matters — you can only unstage what's already been staged.
For a more granular view of exactly what lines are staged, use:
git diff --staged This shows you the diff between your last commit and the current staging area — useful when you've added a file but only want to keep part of it staged.
Partial Unstaging: Removing Only Some Changes in a File
Sometimes you've staged a file but only want to commit part of it. Interactive staging handles this without unstaging the whole file.
git add -p filename.txt The -p (patch) flag breaks the file into individual hunks — small sections of changes — and lets you decide which ones to stage. You can run the same approach in reverse using:
git restore -p --staged filename.txt This walks through each hunk and asks whether to unstage it, giving you surgical control over exactly what goes into your next commit.
Variables That Affect Which Approach Works for You 🔧
Not every environment is the same, and the right command depends on a few factors:
Git version:
git restorewas introduced in Git 2.23 (released 2019). On older systems — legacy servers, embedded environments, or rarely-updated machines —git reset HEADis the safe fallback. Check your version withgit --version.GUI vs. command line: Most Git GUIs (VS Code's source control panel, GitKraken, SourceTree) expose unstaging through a right-click menu or drag-and-drop. The underlying commands are the same, but the interface hides them. If you're working visually, unstaging is usually a single click — the complexity only surfaces when something doesn't behave as expected.
Team workflows and hooks: Some projects use pre-commit hooks or lint-staged configurations that affect what happens during
git addorgit commit. If your team's setup involves automation at the staging step, unstaging and re-adding might trigger those checks again.Monorepos and large codebases: Running
git restore --staged .across a massive repository with thousands of files behaves the same technically, but takes longer and is harder to audit. In those environments, targeted file-by-file unstaging is usually safer.Experience level: If you're new to Git,
git restore --stagedis easier to reason about. If you're comfortable with the reset model and working from documentation written before 2019,git reset HEADis equally valid.
The mechanics are simple. What varies is the context — your Git version, your environment, how much of a file you want to unstage, and whether you're working solo or inside a team with established conventions.