Skip to content

Build1 publisher3 min readPublished

The column M sits in decides whether git restore keeps your edit or deletes it

A dev.to walkthrough runs each undo case in a throwaway repo on git 2.43.0. Status columns tell you where the change lives; whether a colleague already pulled the commit is the part you have to know yourself.

The Engineer · Build desk

What happened

  • A dev.to walkthrough reduces "how do I undo a commit" to two questions asked before typing: where the change lives, and whether anyone else already has it.
  • Each case was run in a disposable repository on git 2.43.0 holding three commits that touch a single file, with the real terminal output printed.
  • In the staged case, restore --staged unstages the change and leaves the file intact, while running restore on the path afterwards destroys the edit the user meant to keep.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint You can answer the first of the two questions from the repository. Status columns locate the change; whether a colleague has fetched the commit is knowledge the working copy does not hold.
  • exposure The cost of a rewrite on a pushed commit lands on everyone who already cloned, not on the person who typed it, and it arrives as a merge of history they no longer have.
  • decision Fixing a bad commit message is a push-status call: amend while the commit is local, revert once it is not.
  • capability With a simulator that refuses the shared-commit rewrite and prompts on reset --hard, the two mistakes that cost colleagues an afternoon can now be made somewhere they cost nothing.

Two columns in `git status --short` answer the first question. An edit that has only been written to the file prints `M config.txt` with the M in the second column, and `git restore config.txt` puts the file back with status printing nothing afterwards [3]. Stage the same edit and the M moves to the first column [4]. The letter is identical; the column tells you which form of `restore` applies.

The staged case is where the second command does the damage. `git restore --staged config.txt` takes the change out of the index and leaves the file alone, so status goes back to an M in the second column, and `git reset config.txt` does the same job [5]. Running `git restore config.txt` after that discards the edit you had just decided to keep [6].

For a commit nobody else has, `git reset --soft HEAD~1` moves the branch pointer and nothing else [8]. The transcript's three-commit repo comes back with two entries, `76ca1c4 Add line3` and `333e24f Initial config`, and the removed commit's content is sitting staged [2][8][10]. Bare `reset` also unstages, and `--hard` also throws the file changes away [9]. A bad message alone is `git commit --amend -m "better message"`, with the same condition attached: only while nobody else has it [11].

Once the commit is pushed, the post rules both out. "Rewriting removes a commit that your colleagues' branches are built on; their next pull becomes a merge of history you deleted," the walkthrough wrote [12]. `git revert HEAD --no-edit` adds the inverse instead: the log holds `6a6f2b6 Revert "Add line4"` above `d906de1 Add line4`, the commit reports one file changed and one deletion, and config.txt is back to three lines [13].

The reflog does not cover you for `reset --hard`. After an unsaved edit, `git reset --hard HEAD` reports HEAD is now at 778de83 and the next `status` prints nothing [14]. `git reflog | head -2` shows the reset itself and the amend before it, because the reflog records where HEAD pointed and an uncommitted edit never had a commit to point at [15]. The command clears every uncommitted change in the repository, not only the one you were thinking about; the post's advice is to keep `--hard` for "I mean everything" [16].

The second question is yours to answer. Status locates the change; whether a colleague has already fetched the commit is something you have to know for yourself. Inside the browser Practice Mode the simulator does know: it checks repository state, accepts either `git reset config.txt` or `git restore --staged config.txt` for the unstage step, asks you to confirm what `reset --hard` would discard, and refuses a rewrite of a shared commit with the reason [17].

What would have to be true for this to transfer is mostly a question of tooling. The transcripts are git 2.43.0 [2], and the post notes that `git checkout -- config.txt` is the older spelling of `restore` [7]. That is the line to reach for on an image that predates it. The published decision table extends to amend and interactive rebase for older commits, with what each one does to everyone else's clone [18].

What to watch

  • Whether Practice Mode's refusals extend to interactive rebase on an older shared commit as well as to a rewrite of the tip.
  • Whether the simulator's reset --hard confirmation lists the specific uncommitted files it would discard.
  • Whether the amend and rebase rows in the decision table get the same run-it-yourself transcripts as reset and revert.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories