---
title: 'Unstaging and Restoring Files'
source: 'https://academia.sh/en/courses/introduction-to-version-control/unstaging-and-restoring-files'
course: 'Introduction to Version Control'
language: en
updated: '2026-08-17T18:10:48+00:00'
license: 'CC BY-SA 4.0'
---

# Unstaging and Restoring Files

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

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:

```bash
./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:

```bash
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

```bash
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:

```bash
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

```bash
git restore ara.sh
git status --short
```

```
M  terimler.txt
```

```bash
./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:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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.
