cherry-pick vs revert vs reset
Three commands that move or undo commits — knowing which one to reach for is the difference between a clean fix and a mess.
These three get confused constantly because they all "deal with commits." The real question is: am I copying a commit, cancelling one safely, or moving my branch pointer?
cherry-pick — copy a commit here
Applies the changes from a specific commit onto your current branch as a new commit. Use it to backport a fix from main to a release branch, or to grab one commit without merging a whole branch.
revert — undo a commit, safely
Creates a new commit that applies the inverse of a target commit. History is preserved and moves forward, so it is safe on shared branches. This is how you "undo" something already pushed.
reset — move the branch pointer
Rewinds your branch to an earlier commit. Rewrites history, so keep it to local, unpushed work. The mode decides what happens to the changes:
| Mode | Moves branch | Staging | Working dir |
|---|---|---|---|
--soft | yes | kept staged | kept |
--mixed (default) | yes | unstaged | kept |
--hard | yes | discarded | discarded |
Example
# Copy a hotfix from main onto a release branch
git switch release/2.3
git cherry-pick a1b2c3d
# Safely undo a commit that's already pushed
git revert a1b2c3d # new commit that reverses it
git push
# Reshape local, unpushed history: undo last 2 commits but keep the changes staged
git reset --soft HEAD~2When to use it
- A release manager cherry-picks a security fix from main onto release/1.4 to patch the old version without importing unreleased features.
- A developer uses git revert to undo a bad commit that already landed on main and was pushed, because reset would rewrite shared history.
- A developer uses git reset --soft locally to uncommit three WIP commits and combine them into one clean commit before pushing.
More examples
cherry-pick to port a fix
cherry-pick copies the diff of one specific commit onto the current branch, creating a new commit with the same changes.
# Port the security fix to the release branch
git switch release/1.4
git cherry-pick e4a1f3c
# [release/1.4 7b2c9d1] fix: patch SQL injection in search
# 1 file changed, 3 insertions(+), 1 deletion(-)revert to undo a published commit
revert creates a new undo commit that leaves the original commit in history, making it safe for already-published shared branches.
# Undo a commit that is already on the shared main branch
git revert a1b2c3d
# [main 9f0e1d2] Revert "feat: add experimental dark mode"
# The original commit is still in history
git log --oneline | head -4reset to rewrite local history only
reset rewrites branch history by moving the HEAD pointer; use --soft to keep changes, --hard to discard them — but never on already-pushed commits.
# Uncommit last 2 commits, keep changes staged
git reset --soft HEAD~2
# Or discard changes entirely (dangerous)
git reset --hard HEAD~2
# Only safe before pushing to a shared remote
Discussion