Git Undo & History | reset, revert, and rebase explained
이 글의 핵심
Safely undo commits and clean history with reset, revert, restore, and rebase—when to use each on shared branches.
Git in practice #4: Undo, rebase, and cleanup
Previous: Remote repos and collaboration (#3) covered push, pull, and PRs.
When you need to undo commits or tidy history, the usual tools are reset (move HEAD and optionally index/worktree), revert (create a new commit that undoes another), and rebase (replay commits on top of another tip). This article explains what each does and when to be careful.
After reading you will:
- Understand
git reset --soft,--mixed,--hard, and how they differ fromgit restore/git switch - Know when to pick
git revertvsgit reset, including after a push - Use
git rebase, interactive rebase (squash, fixup, reword, edit), and resolve rebase conflicts - Recognize risks of
git reset --hardandgit push --force, recover with reflog, and align with merge vs rebase team rules
Table of contents
- Overview
- git reset
- git revert
- git rebase
- Practical cautions
- FAQ
- Command comparison
- Rebase deep dive
- Scenarios
- Dangerous commands and recovery
- History and team policy
1. Overview
| Goal | Command | Behavior |
|---|---|---|
| Undo the last commit but keep changes staged | git reset --soft HEAD~1 | Moves HEAD; index and working tree unchanged |
| Undo commit + unstage | git reset HEAD~1 (or --mixed) | Commit and staging undone; files stay modified |
| Hard reset to a commit (destructive) | git reset --hard HEAD~1 | Commit, index, and working tree match that commit |
| Undo a pushed change safely | git revert <commit> | Adds a new commit that reverses the target |
Linear history on top of main | git rebase main | Replays your commits (rewrites hashes) |
If a commit is already on the remote, avoid “deleting” it with reset --hard + force push—use revert to add an explicit undo commit. Use rebase mainly on local branches not yet pushed (or per team rules).
2. git reset
reset —soft
Only removes the commit; staging and working tree stay:
git reset --soft HEAD~1
Typical uses:
# Fix the last commit message
git commit -m "Fix bug"
git reset --soft HEAD~1
git commit -m "Fix authentication bug"
# Add a forgotten file to the last commit
git commit -m "Add feature"
git reset --soft HEAD~1
git add forgotten_file.js
git commit -m "Add feature"
# Squash last 3 commits locally
git reset --soft HEAD~3
git commit -m "Implement user authentication"
HEAD shortcuts: HEAD~1, HEAD^, HEAD~3, or a specific hash.
reset —mixed (default)
Undoes the commit and staging; changes remain unstaged.
git reset HEAD~1
# or
git reset --mixed HEAD~1
Then git add selectively and commit again.
reset —hard
Moves commit, index, and working tree to the target—uncommitted work is lost. Stash or branch first if you might need it.
git reset --hard HEAD~1
Avoid on shared branches; combined with force push it rewrites teammates’ bases.
3. git revert
revert applies the inverse of a commit as a new commit—history stays linear and auditable.
git revert HEAD
git revert abc1234
git revert -m 1 <merge_commit_sha> # pick parent for merge commits
reset vs revert (already pushed):
# reset: removes C from history (bad if others pulled C)
# revert: adds C' that undoes C (safe for collaboration)
Conflicts during revert: fix files → git add → git revert --continue, or git revert --abort.
4. git rebase
Rebase replays your branch’s commits on top of another tip (often main). Commit hashes change—do not rebase commits others have already pulled unless coordinated.
git switch feature/login
git rebase main
On conflicts: edit → git add → git rebase --continue, or git rebase --abort to cancel.
Rules of thumb:
- Prefer rebase on local-only feature branches.
- Do not rebase shared integration branches like
maincasually.
5. Practical cautions
- Before push: reset/rebase locally as you like.
- After push: prefer revert for bad releases; force push only with team agreement.
- merge vs rebase: many teams merge into
mainand rebase feature branches only—pick one policy and stick to it.
6. FAQ
Can I recover after reset --hard?
Often yes, immediately via git reflog to find the old HEAD and reset to it. Older entries may be pruned—do not rely on it as backup.
revert vs reset?
reset moves HEAD and can drop commits from the recorded history. revert adds a new commit; safer when others share the branch.
Conflicts during rebase?
Edit conflict markers, git add the files, git rebase --continue. Use git rebase --abort to go back to pre-rebase state.
Closing
reset --soft/--mixed: undo commits (and maybe staging) while keeping work—great locally.reset --hard: destructive; avoid on pushed shared branches.revert: add an undo commit—preferred for shared history.rebase: linearize history—best on unpushed feature branches.
One line: Use reset/rebase locally; use revert on shared branches. Continue from the Git series index.
Previous: #3 Remote collaboration
Reset touches three layers (summary)
flowchart LR
subgraph layers [Per commit]
H[HEAD / commit]
I[Staging index]
W[Working tree]
end
H --> I --> W
--soft moves HEAD only; --mixed also matches the index; --hard aligns all three to the target commit.
- Push, pull, and PRs
- Branches and merge conflicts
- Git basics
Practical tips
Debugging
- Read compiler and linter messages first
- Reproduce with a minimal example
Performance
- Measure before optimizing
- Define what “fast enough” means
Code review
- Match team conventions
- Check edge cases reviewers care about
Checklist
Before you rewrite history
- Is this the smallest safe change?
- Will teammates understand the result?
- Any performance or release constraints?
While resolving conflicts
- Are merges intentional and tested?
- Edge cases covered?
- Error handling appropriate?
During review
- Intent clear?
- Tests updated?
- Docs updated if behavior changed?
Keywords (search)
Git, undo, reset, revert, rebase, reflog, restore, interactive rebase, force push, commit history
Related posts
- Git basics
- Branches and merging
- Remote collaboration
- Git series index