Mistakes are inevitable in software development, and Git provides several commands to correct them safely. The most powerful and dangerous is git reset <commit>, which moves the branch pointer to a previous commit. Depending on the flags used, reset behaves differently: --soft keeps changes staged, --mixed (the default) unstages them but preserves them in the working directory, and --hard discards them entirely. Because reset rewrites history by relocating the branch pointer, it is dangerous when the affected commits have already been shared.
A safer alternative for shared history is git revert <commit>, which creates a brand-new commit that undoes the changes introduced by the specified one. Unlike reset, revert preserves the existing commit chain, making it appropriate for branches that collaborators have already pulled. The choice between the two comes down to whether history should be rewritten privately or extended publicly.
When developers want to borrow a specific change rather than an entire branch, git cherry-pick <commit> applies the named commit onto the current branch, creating a new commit with the same content but a different hash. To recover work thought to be lost, the reflog, accessed via git reflog, records every reference update such as checkouts and resets, making it possible to find and restore commits that have been abandoned; entries remain valid for roughly thirty to ninety days by default. Recovery is typically performed by combining the reflog with git cherry-pick or git reset. For pinpointing the commit that introduced a bug, git bisect performs a binary search through history, letting developers mark commits as good or bad until the offending one is identified. To revise the most recent commit, git commit --amend replaces it with the currently staged changes and/or a new message, though it should not be used after the commit has been pushed to a shared branch.