Git and GitHub / Intermediate: collaborative change management / Lesson 11
Revert, reset, and choosing the right undo
Choose correction by the state being changed and whether collaborators already depend on the history.
On this page
Lesson goals
- Distinguish inverse commits from reference and file movement.
- Preserve shared ancestry and local work during correction.
Name the state you intend to change
Undo is not one operation. You may want to unstage a path, discard an unwanted working edit, move a private branch, replace an unpublished commit, or counteract a published change. Each touches different state and has different recovery risks. Begin with status, the graph, and the sharing boundary. Preserve valuable uncommitted files independently before a command that can replace them. Do not infer that a command is safe merely because it is common in a tutorial. Ask what must remain reachable and what collaborators must continue seeing after the correction.
Correct a shared change with a new commit
git revert computes an inverse change and records it as a new commit when it succeeds. The original remains in history, preserving an explanation of what happened. This often fits shared-history correction, but the inverse can conflict or require adaptation when later work depends on the original. The lab fragment reverses the latest ordinary commit on a clean temporary branch. It does not move the branch backward. Test the resulting behavior and inspect whether the inverse accidentally removes something now required by subsequent design changes. A successful revert is a textual result, not a guarantee of product recovery.
git -c user.name="Lab Author" -c user.email="lab@example.invalid" revert --no-edit HEAD
git log -2 --format=%s
Requires a clean lab and an intended ordinary non-merge HEAD commit. The log shows a new Revert subject followed by the original subject. Exact quoting can depend on the original message; both commits remain reachable.
Read reset by its destination effects
In its commit-moving form, reset can move the current branch and update the index or working tree depending on mode. --soft moves the branch while leaving index and working content; the usual mixed mode also resets the index; --hard can replace tracked working content and can remove obstructing untracked paths. Path-based reset has different scope and does not move the branch. These distinctions matter more than the label undo. Destructive forms remain non-runnable editorial examples and are not executed on the workspace. A recovery ref preserves commits, but it does not automatically save uncommitted file content.
Inspect a private soft reset without discarding files
The example assumes two clean commits on a private temporary branch and creates a safety reference first. Moving HEAD back one parent with --soft leaves the former tip’s content staged relative to the earlier commit. This can support regrouping unpublished work, but it rewrites the branch’s visible history and must not be applied casually to shared refs. Inspect the staged patch and current branch after the operation. If the branch had uncommitted work before the command, its state would require additional reasoning; keep the lab setup clean and explicit.
git branch safety/before-soft-reset
git reset --soft HEAD~1
git diff --cached --name-only
git rev-parse --verify safety/before-soft-reset
Only the temporary lab branch is moved. The staged name list includes the last commit’s changed paths, and the safety reference still resolves to the original tip. The generated id is not fixed output. No hard reset or real shared-reference update is performed.
Treat merge reversals as graph decisions
Reverting a merge requires choosing the mainline parent so Git knows which side’s change to reverse. This is not the same as erasing the merge from ancestry. Later merges use the retained graph and may not reintroduce changes simply because the merge’s content was reverted. Review the parent relationship, intended future integration, and tests with maintainers before such a correction. Secret exposure is another separate case: deleting a file or reverting a commit does not revoke credentials or remove historical copies. Follow the credential owner’s response and an authorized history-cleaning plan when needed.
Common errors and fixes
A shared branch is moved backward unexpectedly
- Why it happens
- Private reset advice was applied to published history.
- How to fix it
- Preserve refs, coordinate recovery, and use a reviewed shared correction.
- Prevent it next time
- Classify sharing state before choosing undo.
A safety branch does not recover uncommitted edits
- Why it happens
- Commit reachability was confused with working-file backup.
- How to fix it
- Look for independent file backups and preserve current state.
- Prevent it next time
- Save valuable uncommitted content before destructive operations.
A reverted secret is assumed harmless
- Why it happens
- History visibility and credential validity were conflated.
- How to fix it
- Invoke credential revocation and authorized exposure response.
- Prevent it next time
- Prevent secrets entering commits and review staged content.
Check your understanding
1. A published bug needs correction while preserving collaborators’ ancestry. Which starting approach fits?
Show worked solution
A new corrective commit or reviewed revert usually preserves shared history. Inspect dependencies and test the result. Rewriting the branch tip can disrupt collaborators and is not justified merely because reset appears shorter.
2. After a clean private soft reset, where is the last commit’s content?
Show worked solution
It remains in the index and working tree, staged relative to the earlier HEAD. The old commit remains reachable through the safety reference created beforehand. Verify both states before regrouping the work.
Key takeaways
- Choose undo by state, sharing, and recovery requirements.
- Revert adds history; reset can move references and file state.
- Commit recovery does not guarantee recovery of uncommitted edits.