How to git reset --hard only deleted files and keep existing files intact?

84 views Asked by At

Let's say I have files A, B, C, D in my repo. All of them has been modified from the last commit, but not staged yet. Due to a syncing bug, A and B are deleted. I understand that changes in them are gone, but at least I want to recover them from the last commit. Is there a way to git reset --hard only deleted files while keeping existing files intact? Assuming there are many of them, so I can't git checkout individual files or folders.

1

There are 1 answers

10
VonC On BEST ANSWER

Instead of a git reset --hard, a git ls-files -d might help (coupled with git restore, if you are using Git 2.23+):

git ls-files --deleted | xargs -I {} git restore --source=HEAD -- {}

# For older Git, pre 2.23, before Q3 2019:
git ls-files --deleted | xargs -I {} git checkout HEAD -- {}

it seems that git ls-files only reads files from the working tree and stage?
What about a specific commit?

For listing deleted files from a given commit, you would use git log with a diff-filter, and an empty format:

git log --diff-filter=D --first-parent --pretty=format: --name-only -1 <commit>

In your case, to restore those files from that commit:

git log --diff-filter=D --first-parent --pretty=format: --name-only -1 <commit> | \
    xargs -I {} git restore --source=<commit> -- {}

Or, as LeGEC mentions in the comments, using the same diff-filter with git diff:

git diff --diff-filter=D --name-only <commit>~ <commit> | \
    xargs -I {} git restore --source=<commit> -- {}

if I need to list all the files having been deleted in the last 5 commits, what should I do?

git diff --diff-filter=D --name-only @~5