Skip to content
academia.sh

Lesson 10 / 15

Unstaging and Restoring Files

Undoing the staging-area record and the working-directory content separately; choosing a source, and which situations are recoverable.

Contents

The Basic Cycle was told in one direction: a change is made, staged, committed. This topic takes up the reverse direction. The first lesson defines the two narrowest-scoped operations; neither touches history, both affect only the working directory and the staging area.

The distinction has to be established from the start, because the two operations undo different things, and one costs more than the other.

Two Separate Kinds of Undoing

Operation Region affected Source What is lost
Unstaging Staging area Last commit Nothing
Restoring a file Working directory Staging area or a commit Unrecorded edits

The first operation is reversible: unstaged content keeps standing in the working directory. The second is not — if the edit in the working directory was not stored anywhere, it is gone once overwritten.

The Mistake

While two terms are being added to the term list, an edit is also made to the search script: the -x option is added to the grep call. This option requires the match to cover the whole line, and it breaks the script:

./ara.sh yığıt
eşleşme yok: yığıt

The term is in the list, yet it cannot be found: -x requires the pattern “yığıt” to equal the entire yığıt | stack line. Without the mistake being noticed, two changes are staged together:

git add .
git status --short
M  ara.sh
M  terimler.txt

The term addition should be kept; the edit in the script should be undone.

Unstaging

git restore --staged ara.sh
git status --short
 M ara.sh
M  terimler.txt

ara.sh’s mark moved from the first column to the second: the file is no longer in the staging area, it is changed only in the working directory. The command returned the staging-area entry to its state at the last commit; it did not touch the working directory.

To confirm this, the diff is taken:

git diff
diff --git a/ara.sh b/ara.sh
index 582ddde..fd7e235 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,7 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-if ! grep -i -- "$1" terimler.txt; then
+if ! grep -ix -- "$1" terimler.txt; then
     echo "eşleşme yok: $1" >&2
     exit 2
 fi

The edit is still standing. At this point there are two options: fix the edit by hand, or undo it entirely.

Restoring the Working Directory

git restore ara.sh
git status --short
M  terimler.txt
./ara.sh yığıt
yığıt | stack

The script works again. git restore returned the file to its state in the staging area; and since the staging area is identical to the last commit, the result is the file’s state at the last commit.

This command is destructive. The edit it undoes was never stored anywhere; it had no record in the object database or in the staging area. After the command runs, that text cannot be brought back. As a rule, it should not be run without being certain the edit to be undone is really unwanted; if there is any doubt, the change should first be staged or put in the stash. The stash is the subject of this topic’s fifth lesson.

The remaining change is committed:

git commit -m "Öbek ve dizi terimlerini ekle"
[main bfe57d3] Öbek ve dizi terimlerini ekle
 1 file changed, 2 insertions(+)

Choosing the Source

By default, git restore’s source is the staging area. The --source option makes another commit the source:

git restore --source=HEAD~1 terimler.txt
git diff --stat
 terimler.txt | 2 --
 1 file changed, 2 deletions(-)

The file returned to its state at the previous commit; two lines were removed. This is a way to inspect a past version or bring back a single file. The change is only in the working directory; history stays as it was, and git restore terimler.txt returns to the latest state.

The regions the command affects can be chosen explicitly:

Form Affected
git restore <path> Working directory
git restore --staged <path> Staging area
git restore --staged --worktree <path> Both

The third row returns a file entirely to its state at the last commit.

Bringing Back a Deleted File

Deletion is a change too, and it is undone with the same tool. If the term list is deleted by mistake:

git status --short
 D terimler.txt

The D mark is in the second column: the file has been removed from the working directory, but its record in the staging area is still standing. Since the record carries a blob ID, the content is in the object database:

git restore terimler.txt
git status --short

The second command prints nothing; the file has come back. If the deletion was staged too (if D appears in the first column), it is necessary to unstage first, then restore; --staged --worktree does both in a single command.

This is a direct consequence of the previous section’s criterion: the deleted file’s content was tracked, so it was in the object database. When an untracked file is deleted, it cannot be brought back.

Older Forms

The same jobs can be done with older commands, and these forms are common in documentation:

git reset HEAD terimler.txt      # unstaging
git checkout -- terimler.txt     # restoring the working directory

The first command prints this notice:

Unstaged changes after reset:
M	terimler.txt

The problem with the two older forms is that the commands are overloaded: git reset is also the command that rewinds history, git checkout is also the command that switches between branches. The same name producing very different results makes it hard to read which operation is being done from the command. git restore and git switch were defined to name this distinction. The older forms remain valid; this course will use the new names.

What Can Be Recovered

The limit of the undo tools reduces to a single criterion: was the content written to the object database?

State In the object database Recoverable
Committed content Yes Yes
Staged content Yes (as a blob) Yes
Working-directory-only edit No No
Untracked file No No

The second row can be unexpected: the moment git add runs, the content is written as a blob and stays in the database even if no commit follows. Even content that has been unstaged and then overwritten can still be read with git cat-file, as long as its ID is known. An edit that was never staged, by contrast, leaves no trace at all.

The practical consequence is this: a change worked on over a long stretch is protected against a destructive command if it is staged from time to time. This is the staging area’s second function, beyond preparing for a commit.

Summary

  • Unstaging affects the staging area, restoring a file affects the working directory.
  • git restore --staged returns the record to its state at the last commit and loses no data.
  • git restore undoes the edit in the working directory destructively.
  • With --source, a commit can be chosen as the source; --staged --worktree restores both regions at once.
  • The criterion for recoverability is whether the content was written to the object database; staging provides this guarantee.

Next Step

These tools undo changes that have not yet been committed. What happens if a commit that has already been written is missing something or has a mistake? The next lesson takes up amending the last commit, why this operation produces a new object, and in which situations it should not be used.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close