Undoing and Cleaning Up

Some commands in this group move only the index; others delete local changes. Before execution, determine whether you intend to undo “staging state” or file content itself.

git restore <file>

git restore -- README.md

Purpose: restore a specified working-tree path from index contents. It is equivalent to restoring from HEAD only when index and HEAD are identical.

To explicitly ignore the index and restore from the current commit:

git restore --source=HEAD -- README.md

Legacy form:

git checkout -- README.md

Local content can be lost

If this file contains modifications not saved in a commit or stash, running the command overwrites them.

Inspect first:

git diff -- README.md

git restore --staged --worktree <file>

git restore --staged --worktree -- README.md

Purpose: undo both staged content and working-tree content for the file, returning it to current HEAD.

Legacy form:

git checkout HEAD -- README.md

Appropriate when:

  • a file has been staged, but you have confirmed none of its changes are wanted.

This is stronger than git reset -- README.md because it changes working-tree content.

git revert: undo a commit while preserving history

git revert --no-edit HEAD

Purpose: generate inverse changes for a target commit and create a new commit. It does not delete the original commit, so it suits ordinary commits in shared history.

Before using it:

  • inspect the target with git show HEAD; in practice, revert only a dedicated ordinary test commit;
  • keep the working tree clean; if inverse changes conflict, resolve them and continue, or abort with git revert --abort;
  • a merge commit requires selection of a mainline parent, so beginners should not casually revert a merge commit;
  • --no-edit keeps the auto-generated message so practice does not get blocked by an unfamiliar editor. In real projects, still review the message under team policy.

git reset --hard

git reset --hard

Purpose: reset current branch, staging area, and working tree to HEAD, discarding all local modifications to tracked files.

High-risk operation

This deletes uncommitted modifications to tracked files. To write its target commit, it can also delete untracked files/directories that obstruct tracked paths. Reflog cannot recover working-tree content that was never committed. Use only in a disposable isolated repository, after git status --short, git diff, and git diff --staged.

Common safer alternative:

git stash
git status --short

If you only need to unstage content, do not use --hard:

git reset

git clean

git clean

Purpose: delete files not tracked by Git. Real use normally needs -f because Git protectively refuses direct deletion by default.

Recommended flow:

git clean -n -d
git clean -fd
  • -n is a dry run that lists what would be deleted.
  • -f confirms execution.
  • -d includes untracked directories.
  • Ignored paths are not deleted by default; -x includes them, and this beginner route does not practice that option.
  • Nested Git repositories have extra protection. Do not stack -f flags to bypass a boundary you do not understand.

It will not enter commit history

Git has not saved untracked files. After deletion, Git usually cannot recover them.

git stash

git stash

Purpose: temporarily save staged and unstaged modifications to currently tracked files, then clean those modifications. If untracked or ignored paths remain, the working tree may not be completely clean.

Appropriate when:

  • you need to switch branches temporarily but current work is not ready to commit;
  • you want to move local modifications aside before pulling updates or reproducing an issue.

Useful supplementary commands:

git stash list
git stash pop
git stash apply
  • pop applies the most recent stash and deletes it after success.
  • apply applies it but retains the stash record.
  • Default git stash does not include untracked or ignored files; -u includes untracked files, while -a includes ignored files too. Inspect first to avoid putting credentials into a stash.

Decision table for an undo command

GoalHistory impactSuitable for shared history?Recommended command
Unstage only; retain file contentsUnchangedYesgit restore --staged -- README.md
Overwrite working-tree file from indexUnchangedYes, but loses local contentgit restore -- README.md
Overwrite index and worktree from HEADUnchangedYes, but loses local contentgit restore --source=HEAD --staged --worktree -- README.md
Inversely undo a shared ordinary commitAdds inverse commitUsuallygit revert --no-edit HEAD
Move local branch while retaining file changesRewrites current branch entryConsider only if not sharedgit reset --mixed HEAD~1
Discard all tracked local changesBranch target can change; files are lostNo; isolated repository onlygit reset --hard HEAD
Delete untracked filesNot in history; normally unrecoverableHistory-independent but high riskFirst git clean -n -d, then consider git clean -fd only in an isolated repository
Temporarily move tracked changes asideHistory unchanged; adds stash referenceLocal operationgit stash push -m "wip: explain purpose"

Minimum exercise

In the isolated repository from Version-Control Practice and Self-Check, verify separately “restore working tree,” “unstage,” and “revert a dedicated ordinary commit.” At each step record status, diff, diff --staged, and log before/after, then state whether content, index, history, and branch pointer changed.

References

Checked against Git 2.55.0 official documentation, obtained 2026-07-14.