RizTech Academy logo
RizTech Academy
Git and CollaborationLesson 5 of 530 min

Undoing things: reset, revert and reflog

Everyone makes mistakes in Git — a bad commit, a change committed to the wrong branch, a file deleted, a reset that went too far. The difference between someone who panics and someone who calmly fixes it is knowing the handful of "undo" tools and, crucially, which to use when. This lesson is undoing things safely: checkout/restore, reset, revert, and the safety net almost nobody teaches beginners — reflog. It closes the Git module.

Undoing uncommitted changes

The simplest case: you edited files, have not committed, and want to throw the changes away or unstage them.

git restore file.txt          # discard uncommitted changes to a file (revert it to the last commit)
git restore --staged file.txt # unstage a file (keep the edit, just remove it from staging)
git restore .                 # discard ALL uncommitted changes — careful, this is destructive

(Older Git uses git checkout -- file and git reset HEAD file for these.) git restore throws away uncommitted work permanently — there is no getting it back, because it was never committed. So look before you run git restore .. If you are unsure, commit or stash first:

git stash          # tuck all uncommitted changes away safely, giving you a clean tree
git stash pop      # bring them back

Stash is a handy "hold this for a moment" — for example when you need to switch branches but are not ready to commit.

Undoing commits: reset vs revert

This is the crucial distinction, and getting it wrong is how people lose work or corrupt shared history.

git reset moves your current branch pointer to an earlier commit — it rewrites history by discarding (or unstaging) the commits after that point. It has three modes:

git reset --soft HEAD~1   # undo the last commit, KEEP its changes staged (redo the commit differently)
git reset HEAD~1          # (--mixed, default) undo the commit, keep changes in the working dir, unstaged
git reset --hard HEAD~1   # undo the commit AND throw away its changes entirely — destructive

reset is for local, unshared commits — tidying up before you push. Because it rewrites history, using it on commits you have already pushed (that others may have) causes the same shared-history problems as rebasing. And --hard deletes work, so it is the most dangerous everyday Git command — be sure before you run it.

git revert does not rewrite history. It creates a new commit that undoes an earlier one, leaving the original in place:

git revert HEAD           # make a new commit that undoes the last commit
git revert a1b2c3d        # undo a specific commit by hash

Because it adds a commit rather than removing one, revert is safe on shared history — it is how you undo something that is already on main and that others have pulled. The rule:

  • reset — undo local, unpushed commits (rewrites history; use privately).
  • revert — undo already-shared commits (adds an undoing commit; safe for everyone).

When you have pushed a bad commit to main, the answer is almost always revert, never reset.

Fixing the last commit: commit --amend

A special, common case: you just committed and immediately notice a typo in the message, or a file you forgot to include. --amend replaces the last commit:

git commit --amend -m "better message"   # change the last commit's message
git add forgotten.txt && git commit --amend --no-edit   # add a file into the last commit

Like reset, --amend rewrites the last commit, so only amend commits you have not pushed. It is the tidy way to fix a just-made commit without an ugly "fix typo" follow-up.

The safety net: reflog

Here is the thing that means you can almost never truly lose committed work, and that turns Git panic into a minor annoyance. Git keeps a log of everywhere HEAD has been — every commit, reset, checkout, merge — in the reflog:

git reflog                # a list of recent HEAD positions, each with a hash
git reset --hard a1b2c3d  # jump back to any of those states

So if you reset --hard and destroy commits, or lose track of a commit after a rebase, the reflog still lists the hash of where you were — and you can get back to it. Even "deleted" commits linger for weeks before Git cleans them up, and the reflog is how you find them. This is the single most reassuring thing to know in Git: as long as work was committed at some point, the reflog can almost always recover it. People who know reflog do not fear reset; people who do not, do. Learn it, and Git mistakes stop being scary.

Check your work

Uncommitted: git restore file (discard a file's changes), git restore --staged file (unstage), git restore . (discard all — destructive, never recoverable since never committed); git stash/stash pop to tuck changes away safely.

reset vs revert (the key distinction): git reset moves the branch to an earlier commit, rewriting history — --soft (keep staged), default (keep unstaged), --hard (delete changes — most dangerous). Use only on local, unpushed commits. git revert adds a new commit that undoes an old one — safe on shared history. Pushed a bad commit to main? Use revert, not reset.

commit --amend replaces the last commit (message or forgotten file) — rewrites it, so only for unpushed commits.

reflog = the safety net: Git logs every HEAD position; git reflog lists them and you can reset --hard back to any. Committed work is almost always recoverable, even after a --hard. Knowing reflog removes the fear of reset.

Practice

  1. Edit a file, then git restore it; edit and stage one, then git restore --staged it — describe what each did.
  2. Use git stash to switch branches with uncommitted work, then git stash pop to bring it back.
  3. Make a commit, then git reset --soft HEAD~1 and re-commit differently; explain what --soft kept.
  4. Make a commit on a shared-style branch and undo it with git revert; explain why revert (not reset) is correct there.
  5. git reset --hard to delete a commit, then use git reflog to find and restore it.
  6. Explain the rule for when to use reset versus revert, and why amending only unpushed commits.

Official documentation

Next: the Containers module.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship