Undoing Changes
Mistakes happen — an edit you didn't mean to keep, a commit you want to take back. Git has a different tool for each stage of "undo," and they behave very differently, so it's worth knowing exactly what each one does before you reach for it.
Discarding an uncommitted edit
If you've changed a file but haven't staged or committed it, and you just want it back to how it was at the last commit:
git checkout -- index.html
# or, the newer equivalent:
git restore index.html
git reset — rewinding commits
git reset moves your current branch pointer back to an earlier commit. It has three modes, and the difference between them matters a lot:
git reset --soft <commit>— moves the branch pointer back, but keeps all the changes from the "undone" commits staged, ready to re-commit differently. Nothing in your working files changes.git reset --mixed <commit>(the default, if you don't pass a flag) — moves the pointer back and unstages those changes, but leaves them sitting in your working files as uncommitted edits.git reset --hard <commit>— moves the pointer back and deletes those changes from your working files entirely, as if they never happened.
git reset --soft HEAD~1
# undoes the last commit, keeps its changes staged
HEAD~1 means "one commit before the current one" — HEAD~2 would go back two, and so on. You can also reset to a specific commit ID from git log.
git reset --hard deletes work with no confirmation and no easy way back once it's gone (and, worse, if you'd already pushed the commits you're erasing, resetting a shared branch can cause real problems for anyone else who pulled them). Only use --hard on commits you're certain nobody else depends on, and consider git commit or a backup branch first if you're not fully sure.git revert — the safer public undo
Instead of rewriting history, git revert adds a brand-new commit that does the exact opposite of an earlier one — leaving the original commit in place, but cancelling out its effect:
git revert 4a1f9c2
[main 9f2b3c4] Revert "Add homepage markup" 1 file changed, 12 deletions(-)
This is the safer choice once a commit has already been pushed and shared: nobody's history gets rewritten, so there's nothing for a collaborator's local copy to conflict with. As a rule of thumb: use reset to clean up commits that only exist locally on your own machine, and use revert to undo something that's already public.