Komitly
BlogPricing
Home/Blog/git reset & git restore: Undoing Mistakes Safely
BasicsBeginner

git reset & git restore: Undoing Mistakes Safely

Komitly·February 27, 2026·10 min read
git resetgit restoregit revertundoreflogdiscard changes
Loading article...

On this page

  • The safety net you need
  • git restore: Discarding working tree changes
  • git reset: Moving the branch pointer
  • Soft, mixed, and hard explained
  • Common undo recipes
  • Undoing in Komitly
  • Summary

Try it visually with Komitly

Stop memorizing commands. See your branches, commits, and merges in a beautiful visual interface.

Download Komitly — Free

Related articles

BasicsBeginner

git init: Creating Your First Repository

Learn how to create a Git repository from scratch. Understand what git init does, what's inside the .git folder, and how to make your first commit.

git initgit addgit commit
6 min
BasicsBeginner

git commit: Saving Your Work Step by Step

Master the git commit workflow. Learn how to stage files, write great commit messages, amend commits, and use visual staging tools.

git addgit commitgit commit --amend
8 min
BasicsBeginner

git status & git diff: Understanding What Changed

Learn how to inspect your repository with git status and git diff. Understand the three file states, read diff output, and review changes before committing.

git statusgit diffgit diff --staged
8 min

© 2026 Komitly

support@komitly.com
BlogPricingChangelogTermsPrivacy

The safety net you need

Mistakes are inevitable. You will commit the wrong files, stage debug code, or realize halfway through that your approach is wrong. The good news is that Git makes almost everything reversible. git restore and git reset are the two tools you need to undo almost any mistake at any stage of the workflow.

The key to using them confidently is understanding where each one operates. Git manages your files across three areas, and each undo command targets a different combination:

Git's three areas and undo commands
Working tree          Staging area          Repository
(files on disk)       (git add)             (git commit)
     │                     │                      │
     │◄── git restore ─────│                      │
     │                     │◄── git restore       │
     │                     │    --staged ──────────│
     │                     │                      │
     │◄───────── git reset --hard ────────────────│
     │                     │◄── git reset --mixed─│
     │                     │    (default)         │
     │                     │                      │
     │                     │◄── git reset --soft──│
     │                     │    (keeps staging)   │
Rule of thumb: use git restore to undo changes to files (working tree and staging area). Use git reset to undo commits (move the branch pointer back).

git restore: Discarding working tree changes

git restore replaces file contents in your working tree or staging area with a version from another source (usually the last commit). It does not move the branch pointer or change commit history.

Discard unstaged changes

The most common use: you modified a file, decided the changes are wrong, and want to go back to the committed version:

Terminal
$ git restore src/App.tsx

Hover over each part to see what it does

To discard all unstaged changes at once:

Terminal
# Discard ALL unstaged changes in the working tree
$ git restore .
$ git status
nothing to commit, working tree clean
Warning: git restore permanently discards uncommitted changes. There is no undo for this operation. If you are not sure, stash the changes first with git stash so you can recover them later.

Unstage files

You staged a file by accident with git add and want to move it back to the unstaged section. Use the --staged flag:

Terminal
$ git restore --staged src/debug.ts

Hover over each part to see what it does

The file contents on disk are not changed. The file simply moves from "Changes to be committed" back to the working tree.

Restore from a specific commit

You can restore a file to its state in any previous commit using the --source flag. This is perfect for recovering deleted files or rolling back a single file without affecting anything else:

Terminal
# Restore a file to its state in a specific commit
$ git restore --source HEAD~2 src/utils/helpers.ts
# Restore a deleted file from the last commit
$ git restore --source HEAD src/old-config.json
$ git restore --source HEAD~2 src/utils/helpers.ts

Hover over each part to see what it does

git reset: Moving the branch pointer

While git restore works on individual files, git reset works on commits. It moves the branch pointer to a different commit, effectively "undoing" one or more commits. What happens to the files from those commits depends on the mode you choose.

Here is the starting point — a commit that you want to undo:

Komitly - Commit Graph (before reset)
e7b8c9dAdd broken feature (oops)main
d6a7b8cUpdate navigation styles
c5d6e7fAdd user authentication
b4c5d6eInitial commit

--soft: Keep everything staged

git reset --soft moves the branch pointer back but keeps all changes from the undone commit in the staging area. This is the gentlest form of reset — nothing is lost:

Terminal
$ git reset --soft HEAD~1

Hover over each part to see what it does

After the soft reset, the branch pointer has moved back but your changes are still staged and ready to be re-committed:

Komitly - After soft reset
d6a7b8cUpdate navigation stylesmain
c5d6e7fAdd user authentication
b4c5d6eInitial commit
Komitly - Changes still staged
Staged (2)
Asrc/features/broken.tsx
Msrc/App.tsx
Changes (0)

Working tree clean

--mixed: Keep changes unstaged (default)

git reset --mixed (or simply git reset with no flag) moves the branch pointer back and clears the staging area, but keeps the changes in your working tree. You can review, edit, and selectively re-stage:

Terminal
# Undo the last commit, keep changes unstaged (default)
$ git reset HEAD~1
$ git status
Changes not staged for commit:
modified: src/App.tsx
Untracked files:
src/features/broken.tsx

--hard: Discard everything

git reset --hard moves the branch pointer back and discards all changes — staged and unstaged. This is the nuclear option:

Terminal
# ⚠ Undo the last commit AND discard all changes
$ git reset --hard HEAD~1
HEAD is now at d6a7b8c Update navigation styles
$ git status
nothing to commit, working tree clean
Warning: git reset --hard is the only reset mode that can permanently destroy uncommitted work. Use it only when you are certain you do not need the changes. If you are unsure, start with --soft — you can always discard changes later.

Soft, mixed, and hard explained

Here is the complete comparison. All three modes move the branch pointer — the difference is what happens to the staging area and working tree:

Reset mode comparison
Mode        Branch pointer    Staging area    Working tree
──────────  ────────────────  ──────────────  ─────────────
--soft      ✓ Moves back      ✗ Untouched     ✗ Untouched
--mixed     ✓ Moves back      ✓ Cleared       ✗ Untouched
--hard      ✓ Moves back      ✓ Cleared       ✓ Cleared

                                               ⚠ DESTRUCTIVE
  • --soft — Use when you want to re-do a commit. The changes stay staged so you can adjust and commit again immediately.
  • --mixed — Use when you want to reorganize changes. The files are unstaged but still on disk, so you can selectively re-stage different parts into new commits.
  • --hard — Use when you want a clean slate. Everything is discarded and you are back to the exact state of the target commit.

The reflog: your ultimate safety net

Even after a --hard reset, the "lost" commits are not actually deleted — they still exist in Git's object database. The reflog records every movement of HEAD, so you can find and recover any commit:

Terminal
# Oops — git reset --hard went too far
# The reflog records every HEAD movement
$ git reflog
d6a7b8c (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
e7b8c9d HEAD@{1}: commit: Add broken feature (oops)
d6a7b8c HEAD@{2}: commit: Update navigation styles
# Recover the lost commit
$ git reset --hard e7b8c9d
HEAD is now at e7b8c9d Add broken feature (oops)
# Commit is back! ✓

The reflog keeps entries for at least 90 days by default. As long as you act within that window, almost nothing is truly permanent in Git.

Common undo recipes

Here are the most common "I need to undo this" scenarios and the exact command for each one:

Terminal
$ git reset --soft HEAD~1
# Changes are staged — edit, re-stage, and commit again
Terminal
$ git reset HEAD
# All files are unstaged but still modified on disk
Terminal
$ git reset --hard HEAD~1
HEAD is now at d6a7b8c Update navigation styles
Terminal
$ git restore src/App.tsx
# src/App.tsx is back to its last committed state
Terminal
$ git restore --source HEAD src/config.json
# File is back on disk exactly as it was in the last commit
Terminal
$ git revert HEAD
[main a1b2c3d] Revert "Add broken feature"
2 files changed, 0 insertions(+), 45 deletions(-)
# Safe to push — history is preserved, change is undone
$ git push
Reset vs. revert: git reset rewrites history — only use it on commits that have not been pushed. git revert creates a new commit that undoes a previous one — safe to use on shared branches because it preserves history.

Undoing in Komitly

Komitly provides several visual tools that make undoing mistakes fast and safe — without memorizing flags or worrying about destructive operations.

The Undo panel

Every Git operation you perform in Komitly is recorded in the Undo panel (accessible from the Activity Rail). It shows a chronological list of your recent operations — commits, resets, rebases, merges, cherry-picks, and stashes — each with a one-click Undo button. Immediately after an operation, a toast notification appears with a quick undo link.

Context menu on commits

Right-click any commit in the graph and you will see options to Reset (soft, mixed, or hard), Revert, and Cherry-pick. The reset option lets you choose the mode from a submenu, so you always know which one you are using.

Discard changes per file

In the staging panel, right-click any modified file and select Discard Changes. Komitly asks for confirmation before discarding — the visual equivalent of git restore <file>, but with a safety prompt.

Discard by hunk or line

Open the diff viewer for a file and you can discard changes at the hunk or individual line level. This is far more precise than discarding the entire file — you can keep the good changes and remove just the parts you do not want.

The Reflog panel

Komitly gives you visual access to the Reflog from the Activity Rail. Instead of parsing terminal output, you see a clean list of every HEAD movement with timestamps and descriptions. Click any entry to navigate to that state, making recovery from accidental resets straightforward.

In Komitly, the Undo panel catches you before you need the Reflog. Every operation has a one-click undo, and destructive actions always show a confirmation dialog first. Combined with hunk-level discard in the diff viewer, you can undo precisely what you need without affecting the rest of your work.

Summary

Undoing mistakes is a core skill in Git. With git restore and git reset, you can reverse almost any change at any stage. Here is a quick recap:

  • git restore <file> — Discard unstaged changes to a file (destructive).
  • git restore --staged <file> — Unstage a file without modifying its contents.
  • git restore --source <commit> <file> — Restore a file to its state in a specific commit.
  • git reset --soft HEAD~1 — Undo a commit, keep changes staged.
  • git reset HEAD~1 — Undo a commit, keep changes unstaged (default --mixed).
  • git reset --hard HEAD~1 — Undo a commit and discard all changes (destructive).
  • git revert HEAD — Create a new commit that undoes the last one. Safe for shared branches.
  • git reflog — Find and recover commits after an accidental reset.
  • In Komitly, the Undo panel provides one-click undo for every operation, the commit graph context menu offers visual reset and revert, and the diff viewer supports hunk-level and line-level discard.

With these tools, mistakes are never permanent. Next, learn how to stage with surgical precision using line-level staging.