Git restore to remote version
Saturday 23/07/2022
·5 min readThe blunt answer is git reset --hard origin/your-branch — it points your local branch at the remote's commit and discards everything local. It works, it's fast, and it throws away any uncommitted changes silently. That last part is why a lot of people use it once, lose work, and never trust it again. Below: the safe way to do this, the unsafe-but-faster way, and what to do if you've already destroyed something.
The one-liner (with the safety steps)
# 1. Make sure your remote ref is up to date
git fetch origin
# 2. Check what you're about to throw away
git status
git diff origin/main # or whatever branch you're resetting
# 3. Reset
git reset --hard origin/main
git fetch origin updates your origin/* refs without touching your working tree. Without it, git reset --hard origin/main resets to whatever your last fetch knew about — which might be hours or days out of date.
The middle step (git status + git diff origin/main) is the difference between "I'm sure" and "I'll regret this." Always look before you reset.
What --hard actually does
git reset has three modes:
| Flag | Moves branch pointer | Resets index | Resets working tree |
|---|---|---|---|
| --soft | yes | no | no |
| --mixed (default) | yes | yes | no |
| --hard | yes | yes | yes |
--hard rewrites your working files to match the target commit, throwing away any uncommitted edits. --mixed keeps your edits as unstaged changes. --soft keeps your edits and keeps them staged.
For "match my remote exactly," --hard is right. For "rewind history but keep my work in progress," use --mixed or --soft.
Safer alternative: stash first
If you have changes you might want, stash them before resetting:
git stash push -u -m "before-reset" # -u includes untracked files
git fetch origin
git reset --hard origin/main
git stash list # confirm it's there
# later, if you want them back:
git stash pop
A stash is recoverable for at least 30 days (controlled by gc.reflogExpireUnreachable). A hard reset is recoverable too — via the reflog — but stashing makes the intent explicit and the recovery one command away.
Recovering after a mistake
If you've already reset and lost work, git reflog is your friend:
git reflog
# 4a2b3c1 HEAD@{0}: reset: moving to origin/main
# 8d9e0f7 HEAD@{1}: commit: my last work-in-progress
# ...
Each line is a commit your local repo remembers, even if no branch points at it. To restore:
git reset --hard 8d9e0f7
The reflog only knows about commits — uncommitted changes that were never staged are gone. Stage often (git add), commit work-in-progress aggressively (you can always squash later), and the reflog will save you most of the time.
Other patterns worth knowing
Reset to remote and keep your local changes as a stash
git stash push -u
git fetch origin
git reset --hard origin/main
# your work is in `git stash list`
Discard only specific files (not the whole branch)
git fetch origin
git checkout origin/main -- path/to/file.js
This restores a single file from the remote without touching anything else. Useful when you've gone down a wrong path in one file but want to keep edits in others.
Reset only the index, keep working tree
git fetch origin
git reset origin/main # --mixed is the default
Moves the branch pointer to origin/main but leaves your edits as unstaged changes. Useful for "rewrite my commit history but keep my work."
Force-pull without losing config
If you really mean "make my local exactly mirror the remote," and you want to throw away untracked files too:
git fetch origin
git reset --hard origin/main
git clean -fd # -f force, -d include directories
git clean -fd deletes everything not tracked by git. Including build artifacts, env files, IDE config you may not have wanted to lose. Use -n first for a dry run.
What NOT to do
- Don't
git pull --force— there's no such flag.git pullrunsfetch+merge(or rebase); to override divergent local work, you have to reset explicitly. - Don't
git push --forcewithout thinking — if your goal is "match remote," you're going the wrong way. Force-push overwrites the remote with your local; you wanted the opposite. - Don't
rm -rfand re-clone — you'll lose stashes, branches, hooks, and config. Reset is faster and safer.
FAQ
What's the difference between git reset --hard and git checkout?
git reset --hard moves your branch pointer and rewrites the working tree. git checkout origin/main puts you on a detached HEAD at the remote commit without moving your local branch. Use reset to move the branch; use checkout to inspect a state without committing to it.
How do I undo a git reset --hard?
Run git reflog to find the commit you were on before the reset, then git reset --hard <commit-sha>. The reflog keeps that history for 30+ days by default. Uncommitted changes that were never staged are not recoverable.
Does git pull overwrite local changes?
No — git pull will refuse to merge if you have conflicting uncommitted changes. To overwrite local changes with remote, you have to explicitly git reset --hard origin/branch or stash first.
Why does git reset --hard origin/main not pull the latest commits?
Because origin/main is a local pointer to the remote that's only updated when you run git fetch. Always git fetch origin first to make sure origin/main reflects the current remote state.