Undoing Changes
git reset HEAD <file>→ Unstage a filegit reset --hard→ Reset to last commit (discard all changes)git revert <commit>→ Create a new commit that undoes changes
git reset
git reset [options] [<commit>]
git reset [<commit>] -- <pathspec>...# Unstage files (keep changes):
git reset # default --mixed
git reset <file> # unstage a specific file
# Unstages changes while preserving modifications in your working directory.
# Rewrite the last commit (keep staged):
git reset --soft HEAD~1
# Moves HEAD back one commit; your changes remain staged to recommit differently.
# Discard local changes:
git reset --hard
git reset --hard <commit>
# Resets index and working directory to match the target; all local changes are lost.
# Reset specific paths to HEAD:
git reset -- path/to/file
# Restores the index entry for that path to the last commit’s version (HEAD) without moving HEAD.- Description: Moves the current branch (HEAD) to a specified commit and optionally updates the staging area (index) and working directory.
- Usage: It move HEAD backward to an earlier commit, reset files from the staging area back to the working directory, reset both index and working directory to match a commit.
- Think Tank: Reset options to work with:
| Option | Description |
|---|---|
--soft |
Reset only HEAD to the target commit |
--mixed |
Reset HEAD and index (default) |
--hard |
Reset HEAD, index, and working directory |
--merge |
Keep non-conflicting local changes when resetting |
--keep |
Reset only if working tree content can be preserved |
How it works: HEAD, index, and working directory:
- Three areas: Git tracks state in the commit tree (HEAD), the staging index, and the working directory.
git resetmanipulates one or more of these depending on the mode you choose. - Core idea: Choose a target commit, then decide whether to update only HEAD, HEAD+index, or HEAD+index+working directory.
- Best Practices:
- Always write clear, descriptive commit messages
- Stage only relevant changes to keep commits focused
- Use
--amendfor quick fixes before pushing, but avoid rewriting public history - Sign commits for security in collaborative projects
- Follow team conventions (e.g., Conventional Commits, semantic messages)
Git - git-reset Documentation

git revert
git revert [--no-edit | --edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] <commit>...
git revert (--continue | --skip | --abort | --quit)# Revert a single commit by hash:
git revert <commit>
# Revert the latest commit (HEAD):
git revert HEAD
# Revert multiple commits (one after another):
git revert <commit1> <commit2> <commit3>
# Stage changes but don’t commit (accumulate reverts):
git revert -n <commit>
# resolve if needed, then later:
git commit -m "Revert <commit> and batch changes"
# Continue/abort during conflicts:
git revert --continue
git revert --abort
git revert --quit- Description: The
git revertsafely undoes past commits by creating new commits that apply inverse changes. - Usage: It creates a new commit that undoes the changes introduced by a specified earlier commit (or commits) without rewriting history. It’s the “safe undo” for shared repositories.
- Think Tank: Reset options to work with:
| Option | Description |
|---|---|
--no-edit |
Use the default generated revert message without opening the editor |
--edit |
Open editor to customize the revert commit message (default behavior) |
-n, --no-commit |
Apply the revert changes to index and working tree without creating a commit |
-m |
When reverting a merge commit, specify which parent is the “mainline” to keep |
-s, --signoff |
Add a “Signed-off-by” line to the revert commit message |
-S[] |
GPG/SSH-sign the revert commit |
--continue |
Continue a revert after resolving conflicts |
--abort |
Abort the ongoing revert and restore the pre-revert state |
--quit |
Stop the revert process, leaving the index and work tree as-is |
- Best Practices:
- Verify the target commit: Inspect with
git show <commit>to confirm what you’re undoing. - Prefer revert on shared branches: Keep history intact and avoid force-pushes.
- Commit messages: Keep the default “Revert <hash>” context and add a clear reason for traceability.
- Test after revert: Run builds and tests to ensure the reverse patch doesn’t introduce regressions.
- Use
-nthoughtfully: Batch related reverts to reduce noise and ease review, but avoid hiding unrelated changes in a single commit.
- Verify the target commit: Inspect with
How it works
- Inverse patch: Git computes the diff introduced by the target commit and applies the inverse of that diff to your working tree and index.
- New commit: The result is recorded as a new commit that references the original commit in its message, preserving an auditable history.
- Clean state required: Revert requires a clean working tree (no unstaged or staged changes) before starting; otherwise it will refuse to run.
- Conflicts possible: If the inverse patch overlaps with newer changes, Git stops and asks you to resolve conflicts, then continue.
Advanced Workflows:
Reverting merge commits
- Mainline parent selection: A merge commit has multiple parents; to revert it, you must choose which parent’s history you’re keeping with
-m <parent-number>. Without-m, Git will refuse to revert a merge commit. - Conflict likelihood: Reverting merges is more prone to conflicts; resolve them and run
git revert --continue.
Reverting a range of commits
- Order matters: Reverting multiple commits applies them in the order you specify; ensure the sequence makes sense to minimize conflicts.
- Batch reverts: Use
-nacross several commits, review the combined changes, then commit once.
Reverting an already reverted change
- Double revert: Reverting a revert re-applies the original change. This is a common technique to “bring back” a change that was previously undone.
Collaboration and auditing
- Why revert vs reset: Revert is history-preserving, making it ideal for shared branches where you must not rewrite history. Reset would move branch pointers and can require force-pushing.
Git - git-revert Documentation


Updated on Dec 23, 2025