Git & GitHub Fundamentals · Module 11 of 12

Undo, recovery, stash and reflog

Choose the least destructive recovery tool for the state you need to change: working tree, index, published history or local reference movement.

Learning objectives

By the end of this module, you should be able to:

  • Distinguish restore, reset and revert.
  • Recover local reference movement with reflog.
  • Use stash deliberately for temporary work-in-progress.

Undo commands change different layers

git restore changes working-tree and/or index content. git reset moves a branch reference and can also affect the index/working tree depending on mode. git revert creates a new commit that inverses an earlier commit, making it suitable for shared history.

Reflog is a local safety trail

Reflogs record recent updates to local references such as HEAD. They can help locate commits after an accidental reset or branch move, subject to repository retention and garbage collection. Reflog is local and is not a substitute for backups.

Stash is temporary, not archival

git stash can park tracked work (and optionally untracked files) while you switch context. Name stashes when useful and apply/pop carefully if conflicts are possible.

Worked examples

See the idea in practice.

Compare safe recovery tools

git restore app.txt
git restore --staged app.txt
git revert <commit>
git reflog --oneline | head
  • restore can discard uncommitted file edits, so inspect first.
  • revert preserves shared history by adding a new commit.
  • reflog helps find recent local reference positions.
Hands-on lab

Lab — Recover from a mistaken local reset

Goal: Create commits, move main backward, then recover the lost tip using reflog.

Before you start

  • Git 2.23 or newer is recommended so the labs can use git switch and git restore.
  • Run labs in a disposable working directory; the included validator creates and removes its own temporary repository.
STEP 1

Create three commits

mkdir -p ~/gnu-git-labs/module11 && cd ~/gnu-git-labs/module11
git init -b main
git config user.name "GNU Learner"
git config user.email "learner@example.invalid"
printf "one\n" > data.txt
git add data.txt && git commit -m "Add one"
printf "two\n" >> data.txt && git commit -am "Add two"
printf "three\n" >> data.txt && git commit -am "Add three"
STEP 2

Record the current tip

git rev-parse HEAD > /tmp/gnu-git-module11-tip
STEP 3

Move main backward intentionally

git reset --hard HEAD~1
cat data.txt
STEP 4

Inspect reflog and recover

git reflog --oneline -5
git reset --hard "$(cat /tmp/gnu-git-module11-tip)"
cat data.txt
STEP 5

Clean helper file

rm -f /tmp/gnu-git-module11-tip

Verify

  • After the first reset, line three disappears.
  • After recovery, line three returns and HEAD matches the recorded commit.

Expected outcome

  • Learners see why reflog can recover recent local reference mistakes.

If it fails

  • Never run reset --hard on valuable uncommitted work without a backup or clear intent.
  • On shared published history, prefer revert unless the team explicitly coordinates history rewriting.
Real-world connection

Production support frequently requires undoing a bad change while preserving an auditable history; revert is usually safer for shared branches.

Avoid these traps

Common mistakes

  • Using reset --hard as a generic cleanup command.
  • Rewriting a shared branch without coordination.
  • Treating stash or reflog as permanent backup storage.
Knowledge check

Can you explain it without looking back?

Open each answer only after you have tried to answer the question yourself.

1Which command creates a new commit that reverses an earlier commit?

git revert.

2What does git reset primarily move?

A branch/reference tip, with optional index/working-tree effects depending on mode.

3What can git reflog help recover?

Recent local reference positions, such as a commit before an accidental reset.