Introduction
Beginners fear Git because they think one wrong command destroys work. The truth is the opposite: Git is the most forgiving tool on your machine — almost every mistake has a named undo. This lesson is the map: restore a file you ruined, unstage a file you added by accident, amend the last commit, and the two big ones — reset (rewrite history; private work only) versus revert (a new commit that cancels an old one; safe anywhere). Plus the stash, your pause button for unfinished work. (Roman Urdu: Git mein taqreeban har ghalti ka undo mojood hai — bas ye jaanna hai ke kaun sa undo kis stage par lagta hai.)
Key points
- Undo depends on the stage: file edited but not staged →
git restore <file>. Staged but not committed →git restore --staged <file>. Committed but not pushed → amend or reset. Pushed → revert. Same mistake, four different doors. git restore <file>is the one destructive undo here: it throws away your unstaged edits and returns the file to the last commit. What was never committed or stashed is gone — read the file once before you restore it.(Roman Urdu: Restore wo edits phenk deta hai jo abhi commit nahi hueen — chalane se pehle aik nazar file par lazmi.)- Amend rewrites the LAST commit only: new message or forgotten file folded in, one clean commit comes out — with a new ID. Golden rule: never amend (or reset) a commit you have already pushed; teammates may have built on it.
- Reset vs revert is the series' most important decision:
resetMOVES the branch label backwards and erases commits from history (private clean-up).revertadds a NEW commit that does the exact opposite of an old one (public, shared, safe). - Stash pauses without committing:
git stashshelves all uncommitted changes and hands you a clean tree;git stash popbrings them back. Perfect for "urgent fix first, my half-done feature later."
Code examples
Example 1 — Restore a ruined file + unstage an accidental add
$ git restore index.html
$ git status
On branch main
nothing to commit, working tree clean
$ git add galat-file.txt index.html
$ git restore --staged galat-file.txt
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: index.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
galat-file.txtWhat it does: you broke index.html with a bad experiment — git restore returns it to the last committed version, and the tree reports clean. Then you staged two files by habit, but one does not belong in this commit: git restore --staged takes ONLY that file back out of the staging area (its content on disk is untouched).
What you will see: the difference between the two restores is everything: plain restore edits the FILE (the bad experiment is gone), --staged edits only the LIST (the file and its contents survive, it simply will not be in the next commit).
Example 2 — Reset: erasing a private commit
$ git log --oneline
h8i9j0k (HEAD -> main) Tajurba jo fail hua
g7h8i9j Setup: project files aur pehla page
$ git reset --soft HEAD~1
$ git log --oneline
g7h8i9j (HEAD -> main) Setup: project files aur pehla page
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: tajurba.htmlWhat it does: HEAD~1 means "one commit before the current one". --soft moves the branch label back one commit and leaves ALL the work staged, ready to recommit differently. Its siblings: --mixed (the default) also unstages, keeping the files; --hard deletes the work entirely — powerful, and the one command in this lesson to type slowly.
What you will see: the failed commit vanishes from the log as if it never happened, while its file sits staged — history rewritten, work preserved. This commit was never pushed, so rewriting is honest. Had it been pushed, the correct tool is Example 3.
Example 3 — Revert: cancelling a PUSHED commit, safely
$ git revert h8i9j0k
[main i9j0k1l] Revert "Tajurba jo fail hua"
Date: Wed Jan 13 09:15:00 2027
1 file changed, 1 deletion(-)
$ git log --oneline
i9j0k1l (HEAD -> main) Revert "Tajurba jo fail hua"
h8i9j0k Tajurba jo fail hua
g7h8i9j Setup: project files aur pehla page
$ git push
To https://github.com/ayesha-khan/notes-app.git
g7h8i9j..i9j0k1l main -> mainWhat it does: the bad commit is already on GitHub where a teammate may have pulled it. git revert does not delete it — it creates a NEW commit that applies the exact inverse (here, deleting the file the bad commit added). You push the revert like any commit; nobody's history breaks.
What you will see: the log keeps BOTH commits — the mistake and its public correction, one above the other. That is not mess; that is an honest audit trail, and it is why revert is the professional's undo for shared work.
Quick recap
- Match the undo to the stage: unstaged edit →
restore; staged →restore --staged; last commit →amend; private commits →reset; public commits →revert. restore(files) andreset --harddestroy uncommitted work — everything else in this lesson is recoverable.- Stash is the pause button: shelve unfinished changes, get a clean tree,
git stash popto resume.
Common mistakes
- Resetting a commit that was already pushed — your local history and GitHub's now disagree, and the next push is rejected (or a force-push breaks a teammate). The fix: pushed = revert; the reset family is for private history only.
git restoreon a file whose edits were never saved anywhere — those lines exist nowhere else, and restore is final. The fix: when in doubt, copy the file aside (orgit stash) first, restore second.- Reverting a revert / reverting a merge blindly — undoing an undo re-applies the original change, which confuses everyone including you. The fix: read
git logtop to bottom and say the story aloud before reverting anything older than the last commit.
Practice
- In a practice repo: commit a good file, then ruin it with bad edits. Restore it and verify the good version is back. Then stage a second file by "accident", unstage it with
--staged, and confirm withgit statusthat it left the commit list but not the disk. - Make three commits A, B, C. Undo C with
git reset --soft HEAD~1and recommit its work under a better message. Then make a commit D, "push" it (to GitHub if your repo is connected, or just mark it public), and cancel it withgit revert. Read the final log and explain — in one line each — why C got reset but D got reverted.