Course outline · 0% complete

0/28 lessons0%

Course overview →

git restore: throwing away and unstaging

lesson 4-1 · ~9 min · 10/28

Recall from lesson 2-2 that editing soup.txt and running git add soup.txt puts the change in the staging area.

The add copied the change there, and the edited file itself is of course still sitting in the working directory, since staging copies contents rather than moving files. What has not happened is anything in the repository, because only a commit writes there.

Keep that three-zone picture in mind for this whole unit, since every command in it is described by which zone it moves a change out of.

git restore has two jobs

Mistakes are half of programming: an experiment that made a file worse, a git add . that swept up junk. Without a targeted undo you would be hand-editing files back to how you remember them, which is exactly the manual-versioning misery from lesson 1-1.

git restore is the everyday undo for work that has not been committed yet, and it comes in two flavors because uncommitted work lives in two places.

Job 1: throw away working-directory edits.

$ git restore pancakes.txt

This replaces your edited pancakes.txt with the version from the staging area, or from the last commit if nothing is staged. Your recent edits are gone, permanently. Git cannot recover changes it was never given, which makes plain restore the one genuinely dangerous command in everyday use. Reach for it when you have made a mess and truly want out of it.

Job 2: unstage, with --staged.

$ git restore --staged pancakes.txt

This is the exact opposite of git add. The file leaves the staging area while your edits stay safely in the working directory, so nothing can be lost. Completely harmless.

The difference in risk between those two commands is one flag, which is worth pausing on. Neither one prints output on success, so the only signal that you chose wrong is your file's contents afterwards.

Memorizing them cold is not necessary either way, because git status prints both commands as hints beside the files they apply to.

A recorded session

The situation: git add accidentally staged debug-notes.txt along with real work. This session takes it out of the next commit without losing the file.

Each step below shows the command and the output it printed.

Step 1. See the situation.

~/recipe-book $ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   soup.txt
	new file:   debug-notes.txt

Step 2. Pull debug-notes.txt back out of the staging area (status printed the hint).

~/recipe-book $ git restore --staged debug-notes.txt

Step 3. Confirm soup.txt is still staged and debug-notes.txt is back to untracked.

~/recipe-book $ git status
On branch main
Changes to be committed:
	modified:   soup.txt

Untracked files:
	debug-notes.txt

The command that can permanently destroy uncommitted work is git restore notes.txt, without any flag.

Plain restore overwrites your working-directory copy with the staged or committed version. Those edits were never handed to Git, so nothing in .git holds a copy of them and no later command can bring them back.

The --staged form is a different operation despite the near-identical spelling. It empties the waiting room and leaves the file on disk exactly as it is, so the worst outcome is having to run git add again.

To get debug-notes.txt out of the next commit without losing its contents, run git restore --staged debug-notes.txt.

The --staged flag pulls the file back out of the staging area and does nothing else, so the file and its contents remain in the working directory. Since it was a new file, it returns to being untracked.

Both near-misses here are destructive. Plain git restore debug-notes.txt would overwrite the working copy, and rm debug-notes.txt would delete the file outright. The staging area is the only thing that needs to change, so the command that touches only the staging area is the right one.

git restore --staged recipe.txt removes the file from the staging area, undoing a git add.

The working-directory copy, with all your edits intact, is untouched. Only the staged copy is discarded, which is why this is the safe half of restore.

The flag names the zone being emptied, which is a useful way to remember which form does what. git status prints this exact command as a hint under "Changes to be committed", so the reminder is always one command away.