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:

ModeMoves branchStagingWorking dir
--softyeskept stagedkept
--mixed (default)yesunstagedkept
--hardyesdiscardeddiscarded

Example

Example · bash
# 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~2

When 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.

Example · bash
# 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.

Example · bash
# 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 -4

reset 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.

Example · bash
# 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

  • Be the first to comment on this lesson.