lurscher
lurscher

Reputation: 26983

Unstage a deleted file in git

Usually, to discard changes to a file you would do:

git checkout -- <file>

What if the change I want to discard is deleting the file? The above line would give an error:

error: pathspec '<file>' did not match any file(s) known to git.

What command will restore that single file without undoing other changes?

bonus point: Also, what if the change I want to discard is adding a file? I would like to know how to unstage that change as well.

Upvotes: 661

Views: 311872

Answers (8)

irowe
irowe

Reputation: 636

The answer here already addresses the basic case for unstaging a specific file deletion. However, if you accidentally staged the deletion of many files which are mixed in with changes you want to keep, you can use this pipeline of commands:

git diff --staged --name-status | awk '$1=="D"{print $2}' | xargs git restore --staged -- 

The first portion, git diff --staged --name-status, shows all the staged changes with a letter to identify the type of change. Deleted files have a "D".

The second portion prints the file name if the status letter (first column) is "D". This effectively filters the list to just the staged deletions.

The last line calls the git restore --staged command (that the other answers have so helpfuly pointed out) for each deleted file. Note that restore requires git 2.23 or newer, otherwise you will need to use a combination of git reset and git checkout (such as is done in this other answer. For more explanation of git restore, see the git docs or this answer.

Upvotes: 1

KyoungWan
KyoungWan

Reputation: 1

From manual page,

git-reset - Reset current HEAD to the specified state
git reset [-q] [<tree-ish>] [--] <paths>...
In the first and second form, copy entries from <tree-ish> to the index.

for example, when we use git reset HEAD~1 it reset our current HEAD to HEAD~1

so when we use git reset 'some-deleted-file-path'

git assume 'some-deleted-file-path' as some commit point and try to reset out current HEAD to there.

And it ends up fail

fatal: ambiguous argument 'some-deleted-file-path': unknown revision or path not in the working tree.

Upvotes: 0

Geoffrey Wadsworth
Geoffrey Wadsworth

Reputation: 71

I tried the above solutions and I was still having difficulties. I had other files staged with two files that were deleted accidentally.

To undo the two deleted files I had to unstage all of the files:

git reset HEAD .

At that point I was able to do the checkout of the deleted items:

git checkout -- WorkingFolder/FileName.ext

Finally I was able to restage the rest of the files and continue with my commit.

Upvotes: 5

Kreempuff
Kreempuff

Reputation: 723

As of git v2.23, you have another option:

git restore --staged -- <file>

Upvotes: 18

twalberg
twalberg

Reputation: 62489

Assuming you're wanting to undo the effects of git rm <file> or rm <file> followed by git add -A or something similar:

# this restores the file status in the index
git reset -- <file>
# then check out a copy from the index
git checkout -- <file>

To undo git add <file>, the first line above suffices, assuming you haven't committed yet.

Upvotes: 1027

michaeldever
michaeldever

Reputation: 359

If it has been staged and committed, then the following will reset the file:

git reset COMMIT_HASH file_path
git checkout COMMIT_HASH file_path
git add file_path

This will work for a deletion that occurred several commits previous.

Upvotes: 17

seppo0010
seppo0010

Reputation: 15889

Both questions are answered in git status.

To unstage adding a new file use git rm --cached filename.ext

# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   test

To unstage deleting a file use git reset HEAD filename.ext

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    test

In the other hand, git checkout -- never unstage, it just discards non-staged changes.

Upvotes: 71

Ben Jackson
Ben Jackson

Reputation: 93890

The answers to your two questions are related. I'll start with the second:

Once you have staged a file (often with git add, though some other commands implicitly stage the changes as well, like git rm) you can back out that change with git reset -- <file>.

In your case you must have used git rm to remove the file, which is equivalent to simply removing it with rm and then staging that change. If you first unstage it with git reset -- <file> you can then recover it with git checkout -- <file>.

Upvotes: 12

Related Questions