635

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.

3
  • 1
    Discarding changes and unstaging are two different things, which are you trying to do? Mar 6, 2012 at 20:35
  • 1
    This is two different questions and problems in one post. This makes the answers much too and unnecessarily confusing. Jan 26, 2017 at 19:28
  • error: pathspec '<file>' did not match any file(s) known to git. - this error may be simply because the filename is different
    – AMS
    Jul 20, 2022 at 0:42

7 Answers 7

991

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.

11
  • 106
    The -- is the key. git reset <file> doesn't work, which is what brought me here.
    – user711807
    Oct 18, 2016 at 11:12
  • 8
    Why is end-of-options-marker required in the deleted file case only?
    – haridsv
    Nov 13, 2017 at 5:44
  • 9
    @handsv It's not strictly required (you could alternately do git reset HEAD <file>, which is equivalent), but git reset treats its first argument before end-of-options-marker as a ref name, not a file name. Could it be written a bit more flexibly? Probably. Why wasn't it? Probably only the developers know for sure.
    – twalberg
    Nov 13, 2017 at 15:08
  • 4
    @twalberg git reset filename works fine for non-deleted files.
    – Rag
    May 15, 2018 at 0:24
  • 4
    @NeerajB. Manual page synopsis says git reset [-q] [<tree-ish>] [--] <paths>.... If your <file> argument matches the name of a <tree-ish> (a branch, or HEAD or a tag or ...), then it's going to do something other than what you might think, if you don't use --. That's the reason it's there.
    – twalberg
    Mar 13, 2019 at 15:32
69

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.

4
  • 6
    I don't see the hint for a deleted file in git 1.7.2.5 on Debian.
    – tripleee
    Sep 21, 2015 at 10:55
  • Nice to see git status cited; shows users a way to self-help now and next time, and in case information is added or updated in future git versions.
    – Will
    Feb 28, 2019 at 16:39
  • 1
    This is wrong. "Changes to be committed" is what you see before the git reset. After the git reset, you see "Changed but not updated" which means "Changes not staged" in the native language of the git authors, apparently. More importantly, the whole dogma about "git status tells you everything you know" is a lie. (Managers who say that are wasting people's time and should be fired.) May 8, 2019 at 16:25
  • 2
    Generally speaking this is now git restore --staged deleted-file as of at least git 2.24.3 (but could be earlier versions too) Dec 31, 2021 at 0:27
16

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.

1
  • 1
    It's more efficient to git revert COMMIT_HASH
    – Flair
    Aug 26, 2019 at 20:17
12

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

10

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

git restore --staged -- <file>

1

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.

0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.