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
HEADdoesn’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 .
--cachedremoves from the index only; add-rfor 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 --stagedis the cleanest mental model for “unstage only” (Git ≥ 2.23). Use it by default. (Git)git resetremains ubiquitous and works similarly for unstaging; default mode is--mixed. (Git)- On very old Git (<1.8.2),
git resetwithout 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
.gitignorebefore 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 --hardis overkill here; it discards local changes. Not needed just to unstage. (Git)- For directories, remember
-rwithgit 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 addbefore 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 guican 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 .