markmcdermott.io (js, ruby, ...etc) by mark mcdermott

Git Rollback Roundup

Getting Dangerous With Git

05/12/2025

read time:4 mins

I was just working on this blog and realized I had to rollback to a few commits prior. I had to look it up, so thought I would document it here for posterity.

Rollback To X Commit

TypeCommandDanger LevelWhat HappensHistory?Working Directory Afterwards
(Dangerous) Hard resetgit reset --hard <hash>⚠️ HighMoves branch pointer back, deletes all commits after <hash>Commits after <hash> are erasedMatches <hash> exactly (no changes staged or unstaged)
(Dangerous, but keep changes staged) Soft resetgit reset --soft <hash>⚠️ HighMoves branch pointer back, keeps changes from later commits staged in indexCommits after <hash> are erasedLater changes are staged (ready to recommit)
(Safe) Revert commitsgit revert <hash>..HEAD SafeCreates new commit(s) that undo changes after <hash>All commits remain in historyClean working directory (no unstaged changes)
(Safe, with unstaged changes) Revert without committinggit revert <hash>..HEAD --no-commit SafePrepares undo changes but doesn’t commit themAll commits remain in historyLater changes are unstaged (you must commit manually)

There are three more permutations of this chart though:

  1. doing all 4 methods on just the last commit
  2. doing all 4 methods on a single commit (not the last commit though)
  3. doing all 4 methods on a range of commits (but the range ends before the last commit)

Other Rollback Scenarios

1. Rollback of just the last commit

TypeCommandDanger LevelWhat HappensHistory?Working Directory Afterwards
Hard resetgit reset --hard HEAD~1⚠️ HighDeletes the last commitLast commit erasedMatches state before last commit
Soft resetgit reset --soft HEAD~1⚠️ HighRemoves the last commit, but keeps its changes stagedLast commit erasedLast commit’s changes staged
Revertgit revert HEAD SafeCreates a new commit that undoes the last commitLast commit stays in historyClean (no unstaged changes)
Revert without committinggit revert HEAD --no-commit SafePrepares undo of last commit but doesn’t commitLast commit stays in historyLast commit’s changes unstaged

2. Rollback of a single commit that is not the last commit

TypeCommandDanger LevelWhat HappensHistory?Working Directory Afterwards
Hard reset Not practical (would erase all commits after the target)⚠️ Very HighWould require rewriting history and deleting later commitsAll commits after target erasedMatches that earlier commit
Soft reset Not practical (same issue as hard reset)⚠️ Very HighErases all commits after the target, changes stagedAll commits after target erasedThose later changes staged
Revertgit revert <hash> SafeCreates a new commit undoing just that one commitCommit stays in historyClean (no unstaged changes)
Revert without committinggit revert <hash> --no-commit SafePrepares undo of just that one commit, unstagedCommit stays in historyUndo changes are unstaged

3. Rollback of a range of commits (ending before the last commit)

TypeCommandDanger LevelWhat HappensHistory?Working Directory Afterwards
Hard reset Not practical (would wipe all commits after the start of the range)⚠️ Very HighRemoves entire tail of history, including commits after the rangeLater commits erasedMatches earlier commit before range
Soft reset Not practical (same issue)⚠️ Very HighRemoves entire tail, changes stagedLater commits erasedThose later changes staged
Revertgit revert <hash1>^..<hash2> SafeCreates new commit(s) undoing all commits in the rangeCommits stay in historyClean (no unstaged changes)
Revert without committinggit revert <hash1>^..<hash2> --no-commit SafePrepares undo of all commits in the rangeCommits stay in historyUndo changes are unstaged