gitfile-recovery

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


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.


Solution

  • 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