Git has several undo commands because “undo” can mean changing the working tree, changing the staging area, moving a branch, or creating a new commit that reverses an older one.

Choose the command based on where the unwanted change exists and whether its commit has been shared.

Inspect Before Changing Anything

git status
git diff
git diff --staged
git log --oneline --decorate -10

These commands distinguish unstaged content, staged content, and commit history. That distinction determines the safe recovery action.

Quick Decision Table

SituationStarting commandMain effect
Staged the wrong filegit restore --staged <path>Remove it from the next proposed commit; keep working content
Want to discard an unstaged tracked editgit restore <path>Replace working content; destructive
Need to pause unfinished tracked workgit stash pushStore work temporarily and clean the working tree
Need to undo a published commitgit revert <commit>Create a new inverse commit
Need to remove the latest unpublished local commitgit reset --mixed HEAD~1Move the branch back; keep changes unstaged
Need to edit the latest unpublished commitgit commit --amendReplace the latest commit

Warning: Commands that replace working-tree content or move branch history can discard work. Inspect the state and create a safety branch or commit when uncertain.

Unstage Without Losing the Edit

git restore --staged switch1.cfg

This updates the index so the path is no longer part of the proposed next commit. The working-tree edit remains.

before: change is staged + present in working tree
after:  change is unstaged + still present in working tree

Older documentation may use git reset HEAD -- <path> for this operation. git restore --staged expresses the intent more directly.

Discard an Unstaged Tracked Change

git restore switch1.cfg

This replaces the working-tree version with content from the index by default. The discarded working-tree edit is normally difficult or impossible to recover through Git because it was never committed.

Always inspect first:

git diff -- switch1.cfg

Older tutorials often use git checkout -- switch1.cfg. Modern Git provides git restore for file restoration and git switch for changing branches, avoiding the overloaded checkout command.

Temporarily Store Unfinished Work

git stash push -m "WIP before urgent routing fix"

By default, stash saves staged changes and modifications to tracked files, then restores a clean working state. Untracked files are not included unless requested:

git stash push -u -m "WIP including untracked files"

Inspect stored entries:

git stash list
git stash show --patch stash@{0}

Restore the work:

# Apply and keep the stash entry
git stash apply stash@{0}
 
# Apply, then drop the entry if application succeeds
git stash pop

Applying a stash can produce conflicts if the current files changed in overlapping areas.

Note: A stash belongs to the local repository and is not normally transferred by git push. It is temporary working storage, not a team collaboration mechanism or backup.

Revert a Shared Commit

git log --oneline
git revert e871a41

git revert creates a new commit that applies the inverse of the selected commit. The original commit remains in history:

e871a41  Configure Loopback0 on switch1
11123ce  Configure Loopback0 on switch2
295922e  Revert "Configure Loopback0 on switch1"

This is normally safer for a published branch because it adds history instead of moving the branch backward.

A revert can conflict, and reversing an old commit may affect later changes that depend on it. Review and test the result.

For infrastructure, a Git revert changes the desired files. It does not automatically reverse a configuration already deployed to a switch. Deployment and validation are separate steps.

Reset an Unpublished Local Commit

Suppose the latest commit should not remain in local history and has not been shared:

git reset --mixed HEAD~1

The default mixed reset:

  1. moves the current branch to the parent commit
  2. resets the staging area to that commit
  3. leaves the former commit’s file changes in the working tree

The changes can then be edited and committed again.

Reset modes

ModeMoves branchResets indexReplaces working tree
--softYesNoNo
--mixedYesYesNo
--hardYesYesYes

git reset --hard can destroy uncommitted working-tree changes. It should not be used as a generic fix.

Moving a published branch backward also rewrites the history others may have based work on. Prefer git revert for a shared branch unless the team has explicitly agreed to rewrite it.

Amend the Latest Unpublished Commit

Stage the corrected content, then replace the latest commit:

git add switch1.cfg
git commit --amend

To change only its message:

git commit --amend -m "Configure Loopback0 on core switch"

Amend creates a new commit with a different identifier. Avoid amending a commit that others have already fetched unless the shared workflow explicitly allows history rewriting.

Removing a File vs. Stopping Tracking

Remove the file and stage its deletion:

git rm old-switch.cfg

Keep the local file but remove it from the index:

git rm --cached local-settings.cfg

The second command does not erase copies already present in earlier commits. If the file contained a secret, rotate the credential. Merely deleting, reverting, or ignoring the file does not make an exposed secret safe again.

A Safer Recovery Habit

When the correct undo command is unclear:

git status
git diff
git diff --staged
git log --oneline --decorate -10
git branch safety-before-undo

The safety branch gives the current commit a durable name. It does not save uncommitted working-tree content, so stash or commit that content separately if it matters.

Common Mistakes

  • Using git restore <path> before reviewing the unstaged difference
  • Assuming stash includes untracked files without -u
  • Treating stash as a remote backup
  • Resetting a commit already shared with other developers
  • Using git reset --hard when only unstaging was required
  • Believing revert erases the original commit
  • Believing a Git revert automatically rolls back deployed infrastructure
  • Deleting a committed secret without rotating it

TL;DR

  • Inspect working-tree, staging, and history state before undoing.
  • git restore --staged unstages while keeping the edit.
  • git restore <path> discards an unstaged tracked edit.
  • Stash temporarily stores local unfinished work; -u is needed for untracked files.
  • Revert adds an inverse commit and is usually appropriate for shared history.
  • Reset moves a branch and is best restricted to unpublished local work.
  • --hard can destroy uncommitted content.

Resources

Note: Recovery commands and safety boundaries were checked against current Git documentation in July 2026.