Git Reset Local Branch To Remote
Problem
- You ran
git add
(maybegit add .
) and staged the wrong file(s). - You want to unstage (remove from the index) but keep your local edits.
- Sometimes this happens on the first commit where
HEAD
doesn’t exist yet.
Solutions
Modern (recommended, Git ≥ 2.23): unstage without touching your edits
# Unstage one file
git restore --staged path/to/file
# Unstage everything
git restore --staged .
Leaves the working tree unchanged; only removes paths from the index. (Git)
Classic equivalent: git reset
to unstage
# Unstage one file
git reset path/to/file
# Unstage everything
git reset
Default mode is --mixed
; it resets the index to HEAD
for the given path(s) and keeps your edits. In modern Git, git reset
without args also works even before the first commit (old versions errored). (Git, Stack Overflow)
Initial commit (no HEAD
) or when reset
complains: use git rm --cached
# Unstage one file (keep it on disk)
git rm --cached path/to/file
# Unstage everything (recursive)
git rm -r --cached .
--cached
removes from the index only; add-r
for directories. Safe for first-commit workflows. (Git, Stack Overflow)
Preview before changing anything (dry runs)
# See what would be removed from index
git rm -r -n --cached .
# See what would be staged
git add -n .
Good when you staged way too much and want to double-check. (Dry-run flags show actions without applying.) (Git)
Interactive selective unstage (when you only want some hunks)
# Interactive: pick what to unstage
git restore --staged -p
# or older style:
git add -i # option 3 to unstage
Patch/interactive modes let you surgically unstage hunks. (Git, Stack Overflow)
Things to Consider
git restore --staged
is the cleanest mental model for “unstage only” (Git ≥ 2.23). Use it by default. (Git)git reset
remains ubiquitous and works similarly for unstaging; default mode is--mixed
. (Git)- On very old Git (<1.8.2),
git reset
without args failed with noHEAD
; today it empties the index even pre-first-commit. If you ever hit that edge case, usegit rm --cached
. (Stack Overflow) - After unstaging, consider adding entries to
.gitignore
before re-adding. (Thengit add .
again.)
Gotchas
Don’t run git rm
without --cached
unless you intend to delete the file from disk. (Git)
git reset --hard
is overkill here; it discards local changes. Not needed just to unstage. (Git)- For directories, remember
-r
withgit rm --cached
(e.g.,git rm -r --cached .
). (Git)
Sources
- Git docs:
git restore
- Git docs:
git reset
- Git docs:
git rm
- Pro Git Book: Undoing things
- StackOverflow: How do I undo
git add
before commit?
Further Investigation
- Learn the index vs. working tree model (Pro Git, “Reset Demystified”).
- Practice partial staging/unstaging with
-p
(patch mode). - GUI helpers:
git gui
can amend/unstage interactively. ([Git][7], [Super User][8])
Commands to inspect and debug what’s staged/unstaged:
Quick state snapshot
git status
git status --porcelain=v1 # machine-readable; good for scripts
See diffs: staged vs. HEAD, and unstaged vs. index
git diff --cached # staged changes (index → HEAD)
git diff # unstaged changes (worktree → index)
git diff HEAD # everything since last commit
Names/summaries only:
git diff --name-only --cached
git diff --name-status --cached
git diff --cached --stat
Inspect the index and track sets explicitly
git ls-files -s # index (staged) entries with modes/stage
git ls-files -m # tracked & modified in worktree
git ls-files -o --exclude-standard # untracked, respecting .gitignore
Preview exactly what’s staged for a path
git show :path/to/file # show the staged blob
Sanity-check before committing
git diff --cached --stat # concise summary of staged changes
git commit -v # open editor with diff for review
TL;DR
Unstage now, keep edits:
git restore --staged <file> # modern
# or
git reset <file> # classic
First commit / HEAD
issues or whole tree:
git rm -r --cached .