1

I always create a new branch when building a feature. I have done so this time and committed my work to the new branch. However, I noticed that somehow I deleted a file and that was committed as well. So now my feature branch is missing a file that is still in master.

How can I restore the file?

I got the hash of the commit where the files were deleted, and tried:

git checkout 1f1d3f76bac0bf6e13ceee5bb3df69f8389fc73f -- /path/to/MyMissingFile

but git said pathspec did not match any files known to git. I confirmed that both the filename and the commit was correct using git log --diff-filter=D --summary to print the commit and filenames where the deletion occurred.

user101289
  • 9,888
  • 15
  • 81
  • 148
  • I think you could have used the `~` to indicate the first commit before the one you want to fix. `git checkout 1f1d3f7~ -- /path/to/MyMissingFile` – Josh Gust Mar 06 '20 at 23:47

4 Answers4

2

The proper command, with Git 2.23+, would be to use git restore, which replaces the confusing git checkout command.

 git restore -s master -- /path/to/MyMissingFile

That would restore on the working tree only the file as present in the "source" (-s) branch master.

To restore both working tree and index:

git restore -s master -SW -- /path/to/MyMissingFile

(-SW: short for --staged --worktree)

If you only restore the working tree, then a git diff, as illustrated here, will diff between the index (which still reflect the file being deleted) and the working tree.
By restoring the working tree and the index, you add directly the restored file, to then be committed.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • thanks-- can you explain a little more about the difference between the simple restore vs. the restore of both the working tree and index? – user101289 Mar 09 '20 at 15:54
  • @user101289 I have edited the answer. More general information about working tree and index at https://stackoverflow.com/a/3690796/6309 – VonC Mar 09 '20 at 17:06
1

The problem with

git checkout 1f1d3f76bac0bf6e13ceee5bb3df69f8389fc73f -- /path/to/MyMissingFile

is, presumably based on what you said, it's the hash of the commit that deleted the file - so the file isn't there. But the file is in that commit's parent. You can use an abbreviated hash, by the way, and then tacking ^ or ~ onto the end will get the commit's parent. So

git checkout 1f1d3f76ba^ -- /path/to/MyMissingFile

should work. (There would be a potential bit of room for error here if the commit in question is a merge, in that you'd need to make sure you were reaching into the correct parent; but it sounds like that doesn't apply here.)

Switching to the newer restore command is also an option (and probably not a bad idea), as someone else mentioned; but that isn't really the issue at hand.

As you seem to have discovered, you also could reach over into master (or any other branch where the file still exists) and grab the file from there. I don't recommend this, though (especially if you've already gone to the trouble of finding the commit where the file was deleted), because (a) any changes to the file on your branch before its deletion are lost, and (b) any changes to the file on master may be prematurely picked up on your branch. Maybe you know those problems don't apply this time, but it's a bad habit. Next time maybe there's a change you forgot about.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
-1

I was able to fix this issue by simply checking out the files from the master branch, and then committing them to my feature branch:

git checkout master -- /path/to/MyMissingFile
user101289
  • 9,888
  • 15
  • 81
  • 148
-1

The easy way is to use git revert.

  1. Find the commit hash where you made the mistake
  2. Run git revert [commit-hash]

And you'll have your file back

Adam Genshaft
  • 756
  • 10
  • 22