git Distributed version control system, created by Linus Torvalds

Undoing Changes

Which command you want depends entirely on where the change you want to undo currently lives: working directory, staging area, or already committed (and possibly already pushed).

Quick decision guide

You want to…Use
Discard unstaged edits to a filegit restore <file>
Unstage a file (keep the edits)git restore --staged <file>
Rewrite the last commit's message/contentgit commit --amend
Move the branch pointer, keep changes in the working dirgit reset --mixed <commit> (default)
Move the branch pointer and discard all changesgit reset --hard <commit>
Undo an already-pushed commit safelygit revert <commit>
Recover a commit you think you lostgit reflog

Working directory & staging area: git restore

git restore file.txt              # discard unstaged changes to a file
git restore .                     # discard all unstaged changes
git restore --staged file.txt     # unstage, keep the edits in place
git restore --source=HEAD~1 file.txt   # revert a file to an older commit's version

Moving the branch pointer: git reset

git reset <commit> moves the current branch to point at <commit>. What happens to everything after that point depends on the flag:

ModeBranch pointerStaging areaWorking directory
--softmovedunchanged (still has the undone commits' changes staged)unchanged
--mixed (default)movedreset to match targetunchanged (changes become unstaged)
--hardmovedreset to match targetreset to match target — destructive
git reset --soft HEAD~1     # undo last commit, keep changes staged
git reset HEAD~1            # undo last commit, keep changes unstaged
git reset --hard HEAD~1     # undo last commit and discard the changes entirely
git reset --hard origin/main # throw away local commits, match the remote exactly

--hard permanently discards uncommitted work in the reset range. Double check git status and git diff before running it. Never reset commits that have already been pushed and might be in someone else’s history — use revert instead.

Undoing a public commit: git revert

git revert creates a new commit that applies the inverse of an existing one, leaving history intact — safe for commits others may have already pulled:

git revert <sha>             # revert one commit
git revert HEAD~3..HEAD      # revert a range
git revert --no-commit <sha> # stage the revert without committing yet

Recovering lost commits: the reflog

Git rarely deletes a commit outright — even after a reset --hard or a branch deletion, the commit objects usually stick around until garbage collected. The reflog records every position HEAD has pointed to:

git reflog                       # list recent HEAD movements with their SHAs
git checkout <sha-from-reflog>   # inspect a "lost" commit
git branch recovered <sha>       # turn it back into a real branch

The reflog is local-only (not pushed or cloned) and entries expire after 90 days by default (gc.reflogExpire) — treat it as a safety net, not permanent storage.

Removing untracked files

git clean -n     # dry run: show what would be deleted
git clean -f     # delete untracked files
git clean -fd    # also delete untracked directories