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.mdPurpose: 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.mdLegacy form:
git checkout -- README.mdLocal 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.mdgit restore --staged --worktree <file>
git restore --staged --worktree -- README.mdPurpose: undo both staged content and working-tree content for the file, returning it to current HEAD.
Legacy form:
git checkout HEAD -- README.mdAppropriate 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 HEADPurpose: 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-editkeeps 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 --hardPurpose: 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, andgit diff --staged.
Common safer alternative:
git stash
git status --shortIf you only need to unstage content, do not use --hard:
git resetgit clean
git cleanPurpose: 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-nis a dry run that lists what would be deleted.-fconfirms execution.-dincludes untracked directories.- Ignored paths are not deleted by default;
-xincludes them, and this beginner route does not practice that option. - Nested Git repositories have extra protection. Do not stack
-fflags 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 stashPurpose: 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 applypopapplies the most recent stash and deletes it after success.applyapplies it but retains the stash record.- Default
git stashdoes not include untracked or ignored files;-uincludes untracked files, while-aincludes ignored files too. Inspect first to avoid putting credentials into a stash.
Decision table for an undo command
| Goal | History impact | Suitable for shared history? | Recommended command |
|---|---|---|---|
| Unstage only; retain file contents | Unchanged | Yes | git restore --staged -- README.md |
| Overwrite working-tree file from index | Unchanged | Yes, but loses local content | git restore -- README.md |
Overwrite index and worktree from HEAD | Unchanged | Yes, but loses local content | git restore --source=HEAD --staged --worktree -- README.md |
| Inversely undo a shared ordinary commit | Adds inverse commit | Usually | git revert --no-edit HEAD |
| Move local branch while retaining file changes | Rewrites current branch entry | Consider only if not shared | git reset --mixed HEAD~1 |
| Discard all tracked local changes | Branch target can change; files are lost | No; isolated repository only | git reset --hard HEAD |
| Delete untracked files | Not in history; normally unrecoverable | History-independent but high risk | First git clean -n -d, then consider git clean -fd only in an isolated repository |
| Temporarily move tracked changes aside | History unchanged; adds stash reference | Local operation | git 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.