Thuta Learning
IntermediateDevOps & Toolsintermediate

Undoing Mistakes Safely: A Decision Guide

What you'll walk away with

  • Explain the core ideas behind Undoing Mistakes Safely: A Decision Guide
  • Read the diagram and trace how state or data flows through the Git/GitHub workflow
  • Decide how this applies to your own project or team

Build the mental model

Every 'undo' situation in Git comes down to one question: what state is the mistake in right now? Answering that tells you exactly which tool applies.

  • Uncommitted change you want gone -> git restore <file>
  • Staged by mistake, not committed -> git restore --staged <file>
  • Local-only commit, just made -> git commit --amend
  • Local-only commits, further back -> git reset
  • Already pushed/shared commit -> git revert

`git commit --amend` rewrites the most recent commit entirely at the same spot in history; `git reset` unwinds several local commits at once, deciding by mode whether their changes end up staged or in your working directory.

Once a commit is pushed and someone might have pulled it, reach for `git revert` instead — it undoes the change with a new commit rather than rewriting anything, so nobody's clone gets pulled out from under them.

text
WHAT STATE IS YOUR MISTAKE IN?
------------------------------
WHAT STATE IS YOUR MISTAKE IN?
---------------------------------
uncommitted, unstaged change     -> git restore <file>
uncommitted, staged by mistake   -> git restore --staged <file>
committed, local only (latest)   -> git commit --amend
committed, local only (older)    -> git reset
committed, already pushed/shared -> git revert

Connect it to a real scenario

Staged by mistake

Accidentally `git add` a `.env.local`? `git restore --staged .env.local` drops it back to untracked, nothing lost.

Fixing a commit

Realize the commit is missing something? Fix it, stage it, and `git commit --amend` — Git rewrites the previous commit in place.

This ties together earlier lessons

None of this introduces new mechanics — restore, stash, revert, and reset all work exactly as covered before. This lesson is just the map for which one to reach for.

Try the working example

bash
git init -q -b main
git config user.name "Thuta Learner"
git config user.email "learner@example.com"

export GIT_AUTHOR_NAME="Thuta Learner"
export GIT_AUTHOR_EMAIL="learner@example.com"
export GIT_COMMITTER_NAME="Thuta Learner"
export GIT_COMMITTER_EMAIL="learner@example.com"

echo "console.log('core');" > app.js
git add app.js
GIT_AUTHOR_DATE="2026-01-08T09:00:00" GIT_COMMITTER_DATE="2026-01-08T09:00:00" \
  git commit -m "Initial commit"
git branch -M main

echo "SECRET_KEY=abc123" > .env.local
git add .env.local
git status

git restore --staged .env.local
git status
rm .env.local

echo "console.log('feature v1');" >> app.js
git add app.js
GIT_AUTHOR_DATE="2026-01-08T10:00:00" GIT_COMMITTER_DATE="2026-01-08T10:00:00" \
  git commit -m "add feature"

git log --oneline

echo "console.log('feature v1 finished');" >> app.js
git add app.js
GIT_AUTHOR_DATE="2026-01-08T10:05:00" GIT_COMMITTER_DATE="2026-01-08T10:05:00" \
  git commit --amend -m "Add feature v1"

git log --oneline
git show --stat HEAD
You should see
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   .env.local

$ git restore --staged .env.local

$ git status
On branch main
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.env.local

nothing added to commit but untracked files present (use "git add" to track)

$ git log --oneline
deb9ba8 add feature
85d10e3 Initial commit

$ git commit --amend -m "Add feature v1"

$ git log --oneline
06c60a7 Add feature v1
85d10e3 Initial commit

$ git show --stat HEAD
commit 06c60a7d3c9aac1b63ec91514d72939ce4d1825a
Author: Thuta Learner <learner@example.com>
Date:   Thu Jan 8 10:00:00 2026 +0900

    Add feature v1

 app.js | 2 ++
 1 file changed, 2 insertions(+)

5-minute try-it

Stage a file by mistake and use `git restore --staged` to undo it without losing the content. Then make a real commit, realize you forgot something, fix it, and use `git commit --amend` to fold the fix into the same commit instead of creating a new one. Compare `git log --oneline` before and after each step to confirm exactly what changed.

One important caution

`git commit --amend` rewrites the last commit's hash — if you already pushed that commit, amending and pushing again requires a force-push, which carries the same shared-history risk as `git reset` on pushed commits.

`git restore <file>` (without `--staged`) discards the working directory change permanently — make sure you actually want it gone, not just unstaged, before running it.

Git Documentation: git-restoreGit & GitHub

Easy traps

  • `git commit --amend` rewrites the last commit's hash — if you already pushed that commit, amending and pushing again requires a force-push, which carries the same shared-history risk as `git reset` on pushed commits.
  • `git restore <file>` (without `--staged`) discards the working directory change permanently — make sure you actually want it gone, not just unstaged, before running it.
  • Always run `git status` before any destructive or history-rewriting command, to know exactly what state you're in.

Exercise

Stage a file by mistake and use `git restore --staged` to undo it without losing the content. Then make a real commit, realize you forgot something, fix it, and use `git commit --amend` to fold the fix into the same commit instead of creating a new one. Compare `git log --oneline` before and after each step to confirm exactly what changed.

You'll know it worked when: $ git status On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: .env.local $ git restore --staged .env.local $ git status On branch main Untracked files: (use "git add <file>..." to include in what will be committed) .env.local nothing added to commit but untracked files present (use "git add" to track) $ git log --oneline deb9ba8 add feature 85d10e3 Initial commit $ git commit --amend -m "Add feature v1" $ git log --oneline 06c60a7 Add feature v1 85d10e3 Initial commit $ git show --stat HEAD commit 06c60a7d3c9aac1b63ec91514d72939ce4d1825a Author: Thuta Learner <learner@example.com> Date: Thu Jan 8 10:00:00 2026 +0900 Add feature v1 app.js | 2 ++ 1 file changed, 2 insertions(+)

Undoing Mistakes Safely: A Decision Guide | Thuta Learning