[2026] Git reset vs revert — undo commits safely (rebase, reflog, interactive rebase)

[2026] Git reset vs revert — undo commits safely (rebase, reflog, interactive rebase)

이 글의 핵심

Differences between reset, revert, restore, and checkout; interactive rebase (squash, fixup, reword); conflict resolution; force push and reflog recovery; merge vs rebase team rules—practical focus.

[Git in practice #4] Undo, rebase, and cleanup

Previous: Remote repos and collaboration (#3) covered push, pull, and PRs.

Think of a commit as a snapshot of the project. When you need to fix a bad snapshot or straighten a line of snapshots, the main tools are reset (move HEAD to change history, staging, and working tree), revert (add a new commit that undoes another while keeping history), and rebase (replay commits on top of another base to tidy history). This article covers each, including cautions for the last commit, shared branches, and more.

After reading you will:

  • Understand git reset --soft, --mixed, and --hard, and how they differ from git restore and git switch.
  • Know when to choose git revert vs git reset, including patterns after a push.
  • Use git rebase, interactive rebase (squash, fixup, reword, edit), and resolve rebase conflicts.
  • Recognize risks of git reset --hard and git push --force, recover with reflog, and align with merge vs rebase team rules.

Table of contents

  1. Overview
  2. git reset: undo commits and staging
  3. git revert: create a commit that undoes another
  4. git rebase: linear history
  5. Practical cautions
  6. FAQ

1. Overview

GoalCommandBehavior
Undo only the last commit and keep editinggit reset --soft HEAD~1Commit undone; staging and working tree unchanged
Undo commit and staginggit reset HEAD~1 (or --mixed)Commit and staging undone; file edits remain
Fully go back before that commit (risky)git reset --hard HEAD~1Commit, staging, and working tree changes removed
Make a pushed commit look “undone” safelygit revert <commit>New “inverse” commit; history preserved
Linearize branch historygit rebase mainReplays commits on top of main (history changes)

If a commit is already on the remote, using reset —hard and rewriting history conflicts with others—prefer revert to add an explicit undo commit. Rebase changes history, so use it mainly on local branches not yet pushed.


2. git reset

reset —soft

Only the commit is undone; the index and working tree stay as they were:

git reset --soft HEAD~1
# git reset: move the HEAD pointer
# --soft: undo only the commit (keep staging and working tree)
# HEAD~1: the parent of the current HEAD
#
# What happens:
# 1. HEAD moves to the previous commit
# 2. Changes from the undone commit stay staged
# 3. Working tree unchanged
#
# Result:
# git status → changes appear under "Changes to be committed"
# You can git commit again

Typical scenarios:

# Scenario 1: fix the last commit message
git commit -m "Fix bug"  # typo spotted!
git reset --soft HEAD~1
git commit -m "Fix authentication bug"  # corrected message

# Scenario 2: add a file and recommit
git commit -m "Add feature"
# Oops—one file was missing
git reset --soft HEAD~1
git add forgotten_file.js
git commit -m "Add feature"  # all files included

# Scenario 3: squash several commits into one
git reset --soft HEAD~3  # undo last 3 commits
git commit -m "Implement user authentication"  # single combined commit

HEAD notation:

HEAD~1  # one commit back
HEAD~2  # two commits back
HEAD~3  # three commits back

HEAD^   # one commit back (same as HEAD~1)
HEAD^^  # two commits back (same as HEAD~2)

# You can also reset to a specific hash
git reset --soft abc1234

reset —mixed (default)

Undoes the commit and staging; only file edits remain in the working tree. Use when you want to undo the commit and unstage, then stage only part of the changes again.

git reset HEAD~1
# or
git reset --mixed HEAD~1

Then git status shows changes as unstaged; git add what you need and git commit again.

reset —hard

Moves commit, index, and working tree back to the target state. Uncommitted work is discarded, so stash or branch first if you might need it.

git reset --hard HEAD~1

On a branch already pushed, reset —hard followed by force push can break others’ history—avoid in team workflows when possible.


3. git revert

What revert does

revert applies the inverse of a commit as a new commit:

git revert HEAD
# git revert: create a new commit that undoes a given commit
# HEAD: revert the latest commit
#
# What happens:
# 1. Git analyzes the changes in HEAD
# 2. Applies the opposite (add → remove, remove → add)
# 3. Creates a new "Revert" commit
# 4. History is unchanged (old commits remain)
#
# Result:
# A → B → C (HEAD)
#      ↓
# A → B → C → C' (revert of C, new HEAD)
# C' contains the inverse of C

# Revert a specific commit
git revert abc1234
# New commit that undoes abc1234

# Revert a merge commit
git revert abc1234 -m 1
# -m 1: use first parent as base for the revert
# -m 2: use second parent
# Merge commits have two parents, so -m is required

reset vs revert:

# reset: rewrite history (commit disappears)
# A → B → C (HEAD)
git reset --hard HEAD~1
# A → B (HEAD)  ← C is gone from history
# Risk: if others pulled C, histories diverge

# revert: keep history (new commit)
# A → B → C (HEAD)
git revert HEAD
# A → B → C → C' (HEAD)  ← C' undoes C
# Safer for collaboration: full history remains

Revert conflicts:

git revert HEAD
# conflict!

# 1. Edit conflicted files
vim conflicted_file.js

# 2. Stage
git add conflicted_file.js

# 3. Continue the revert
git revert --continue

# Or abort the revert
git revert --abort

Production-style example:

# Scenario: a buggy commit was pushed to production
git log --oneline
# abc1234 Add buggy feature  ← problematic
# def5678 Update docs
# 789abcd Initial commit

# Fix: revert safely
git revert abc1234
# Creates "Revert 'Add buggy feature'"
git push origin main
# History preserved; bug is effectively rolled back

4. git rebase

Meaning

Rebase replays your branch’s commits on top of another branch (or another point). History looks linear, but commit hashes change, so rebasing a branch already pushed without coordination causes problems.

Example: update feature onto latest main

git checkout feature/login
git rebase main

Commits from feature/login are replayed on top of main’s tip. On conflicts: fix files → git addgit rebase —continue. To cancel: git rebase —abort.

Cautions

  • Rebasing a branch already on the remote usually requires git push —force (or --force-with-lease) and can confuse collaborators—prefer local-only branches.
  • Do not casually rebase shared integration branches like main/master.

5. Practical cautions

  • Before push: reset and rebase are fine for local cleanup.
  • After push: to “undo” what was pushed, prefer revert. Use force push only with team agreement.
  • merge vs rebase: standardizing on “merge into main” keeps history predictable; restrict rebase to personal feature branches to reduce surprises.

6. FAQ

Can I recover after reset --hard?

A. Right after reset —hard, git reflog usually shows the previous HEAD. Example: git refloggit reset --hard HEAD@{1} to return. After a long time or after reflog GC, recovery may fail—use branches or stash before destructive resets.

revert vs reset?

A. reset moves HEAD and can make commits disappear from the recorded history. revert adds a new commit without erasing history. For commits already pushed, revert is usually safer.

Conflicts during rebase?

A. Edit conflicts, then git add <file> and git rebase —continue. Repeat if needed. git rebase —abort returns to the state before the rebase started.


Closing

  • reset —soft / —mixed: undo commits (and maybe staging) while keeping work—great for local fixes.
  • reset —hard: resets commit, index, and working tree—avoid on shared pushed branches.
  • revert: add an undo commit—safe for shared history.
  • rebase: linearize history—prefer on unpushed branches.

One line: Use reset/revert/rebase to undo and tidy commits; on branches already pushed, revert is usually the safe choice. See the Git series index for more topics.

Previous: Git in practice #3: Remote collaboration

Series index: Full Git series

Reset touches three layers (summary)

flowchart LR
  subgraph layers [Per commit]
    H[HEAD / commit]
    I[Staging index]
    W[Working tree]
  end
  H --> I --> W

Explanation: --soft moves HEAD only; --mixed also unstages; --hard aligns all three with the base commit.


More on this site

  • Push, pull, and PRs
  • Branches and merge conflicts
  • Git basics

Practical tips

Debugging

  • Read compiler and linter output first
  • Reproduce with a minimal test case

Performance

  • Do not optimize without profiling
  • Define measurable goals first

Code review

  • Check common review feedback early
  • Follow team conventions

Checklist

Before you rewrite history

  • Is this the best fix for the problem?
  • Will teammates understand and maintain the result?
  • Are performance requirements met?

While resolving conflicts

  • Are all compiler warnings addressed?
  • Are edge cases covered?
  • Is error handling appropriate?

During review

  • Is intent clear?
  • Are tests sufficient?
  • Is documentation updated if behavior changed?

Use this checklist to reduce mistakes and improve quality.


Git, undo, reset, revert, rebase, git reset, git revert, reflog, restore, interactive rebase, force push, undo commit, history


  • Git basics
  • Branches and merging
  • Remote collaboration
  • Git series index