Git offers a spectrum of "undo" commands whose power increases from safe to destructive. The lightest touch is git reset --soft HEAD~1, which moves the HEAD pointer back one commit but leaves every change staged for an immediate recommit. The default git reset --mixed HEAD~1 (or just git reset HEAD~1) does the same move but unstages the changes, leaving them in the working tree for inspection. The most destructive is git reset --hard HEAD~1, which discards both staged and working-tree changes entirely, so it should only be used when you are certain the work has no further value. If you want to revise the most recent commit rather than erase it, git commit --amend -m 'new message' rewrites the message, and git add forgotten-file followed by git commit --amend --no-edit folds in files you forgot to include without prompting for a new message.
For mistakes that never made it past the working tree, Git provides the restore family of commands (and older checkout equivalents). git restore file discards local edits to one file, while git restore . throws away every modification in the working tree. To unstage a file you accidentally added, git restore --staged file (or the legacy git reset HEAD file) moves it back to modified-but-not-staged. To temporarily inspect an older state without creating a branch, git checkout <sha> checks out a commit directly and leaves you in detached HEAD; if you decide to keep the work, git switch -c branch-name turns the detached HEAD into a real branch. These commands are safe to run repeatedly because they only touch uncommitted state.
When the wrong branch received a commit, or you simply want to move a single commit between branches, you can rescue it without losing work. From the source branch, run git log --oneline -n 3 to note the commit's SHA, switch to the destination with git switch right-branch, apply the commit via git cherry-pick <sha>, then return to the source and either git reset --hard HEAD~1 (to delete the original outright) or use rebase to drop it more surgically. The same idea works for restoring a single file from any other branch or commit using git checkout HEAD~1 -- path or git checkout branchname -- path/to/file, which writes the historical version of that path into your working tree.
For undoing a public commit that has already been pushed, git revert <sha> is the safe alternative to resetting: it creates an inverse commit that cancels the changes without rewriting shared history, leaving every collaborator's branch intact. This distinction between reset (rewinds locally, dangerous on pushed commits) and revert (adds a new commit, safe on pushed commits) is one of the most important mental models in Git.