English 中文(简体)
How to find a deleted file in the project commit history?
原标题:

Once upon a time, there was a file in my project that I would now like to be able to get.

The problem is: I have no idea of when have I deleted it and on which path it was.

How can I locate the commits of this file when it existed?

最佳回答

If you do not know the exact path you may use

git log --all --full-history -- "**/thefile.*"

If you know the path the file was at, you can do this:

git log --all --full-history -- <path-to-file>

This should show a list of commits in all branches which touched that file. Then, you can find the version of the file you want, and display it with...

git show <SHA> -- <path-to-file>

Or restore it into your working copy with:

git checkout <SHA>^ -- <path-to-file>

Note the caret symbol (^), which gets the checkout prior to the one identified, because at the moment of <SHA> commit the file is deleted, we need to look at the previous commit to get the deleted file s contents

问题回答

Get a list of the deleted files and copy the full path of the deleted file

git log --diff-filter=D --summary | grep delete

Execute the next command to find commit id of that commit and copy the commit id

git log --all -- FILEPATH

Show diff of deleted file

git show COMMIT_ID -- FILE_PATH

Remember, you can write output to a file using > like

git show COMMIT_ID -- FILE_PATH > deleted.diff

Suppose you want to recover a file called MyFile, but are uncertain of its path (or its extension, for that matter):

0. (Preliminary) Avoid confusion by stepping to the git root

A nontrivial project may have multiple directories with similar or identical filenames.

> cd <project-root>
1. Find the full path
> git log --diff-filter=D --summary | grep delete | grep MyFile

`delete mode 100644 full/path/to/MyFile.js`

full/path/to/MyFile.js is the path & file you re seeking.

2. Determine all the commits that affected that file
> git log --oneline --follow -- full/path/to/MyFile.js

`bd8374c Some helpful commit message`

`ba8d20e Another prior commit message affecting that file`

`cfea812 The first message for a commit in which that file appeared.`
3. Checkout the file

If you choose the first-listed commit (the last chronologically, here bd8374c), the file will not be found, since it was deleted in that commit.

> git checkout bd8374c -- full/path/to/MyFile.js

`error: pathspec  full/path/to/MyFile.js  did not match any file(s) known to git.`

Just select the preceding (append a caret) commit:

> git checkout bd8374c^ -- full/path/to/MyFile.js

Could not edit the accepted response so adding it as an answer here,

to restore the file in git, use the following (note the ^ sign just after the SHA)

git checkout <SHA>^ -- /path/to/file

@Amber gave correct answer! Just one more addition, if you do not know the exact path of the file you can use wildcards! This worked for me.

git log --all -- **/thefile.*

Below is a simple command, where a dev or a git user can pass a deleted file name from the repository root directory and get the history:

git log --diff-filter=D --summary | grep filename | awk  {print $4; exit}  | xargs git log --all -- 

If anybody, can improve the command, please do.

Try using one of the viewers, such as gitk so that you can browse around the history to find that half remembered file. (use gitk --all if needed for all branches)

If you prefer to see the size of all deleted file

as well as the associated SHA

git log --all --stat --diff-filter=D --oneline

add a -p|--patch to see the contents too

git log --all --stat --diff-filter=D -p

To narrow down to any file you have two easy options, you can use a pathspec or you can pipe to grep and search for file name.

Using grep:

git log --all --stat --diff-filter=D --oneline | grep foo

Using a pathspec:

git log --all --stat --diff-filter=D --oneline --  *foo* 

A pathspec can work well together with -p|--patch, if you want to see contents:

git log --all --stat --diff-filter=D --oneline --patch --  *foo* 

You might also like this one if you know where the file is

git log --all --full-history -- someFileName

Summary:

  1. Step 1

You search your file full path in history of deleted files git log --diff-filter=D --summary | grep filename

  1. Step 2

You restore your file from commit before it was deleted

restore () {
  filepath="$@"
  last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk  {print $2; exit} )
  echo "Restoring file from commit before $last_commit"
  git checkout $last_commit^ -- $filepath
}

restore my/file_path

Here is my solution:

git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>

I had this happen where I didn t even know what the file s name was, so I wanted to see all deleted files...

In general, I highly recommend becoming familiar with git-filter-repo. It has many uses for re-writing history, but one of its analysis features includes very quickly identifying all deleted files in a repo, and displaying their sizes and date deleted. (Using it on non-Windows OSes is fairly straight-forward, and here are installation instructions specifically for Windows.)

Once you have it runnable in your path, you simply run:

git filter-repo --analyze

This will output some files in your .git folder, and the one you want to look at for this question is called:

.gitfilter-repoanalysispath-deleted-sizes.txt

This file shows all deleted files in your repo, reverse sorted by size, and the date it was deleted. Here s an example output:

=== Deleted paths by reverse accumulated size ===
Format: unpacked size, packed size, date deleted, path name(s)
    57151421   44898377 2022-07-22 somdirectory/somefileA
    46034619   42929136 2022-01-18 somdirectory/somefileB
    65332368   29102439 2020-09-28 somdirectory/somefileC
    23686432   21681498 2022-07-22 somdirectory/somefileD
    23681272   21678818 2022-07-22 somdirectory/somefileE
    23676153   21670502 2022-07-22 somdirectory/somefileF
    43232768   21439037 2020-07-10 somdirectory/somefileG
    18714315   14299243 2019-01-10 somdirectory/somefileH
    16788104   13035176 2019-01-10 somdirectory/somefileI

Obviously you can use this to find the file you re looking for, or, in the context of re-writing history, based on the 2nd column sizes, I know if I remove those 9 deleted files from the history I ll reclaim about 220 MB.

Once you ve identified the file you re looking for you can use this to find the commits:

git log --all --full-history -- <filename>




相关问题
git confusion - cloning a repo is returning a past version

Im having some confusion with my git usage. I cloned a repo from one comp to the other, and the new clone is the state of the original that was active some time ago. So its cloning a past version. ...

Appropriate strategy for tagging and hotfixing with git

I was wondering if the strategy I m using for tagging and hotfixing tags (which then I use for deploying rails applications) with git is appropriate. For tagging I just tag a commit of the master ...

Tips on upgrading CVS to git/hg?

We still use CVS, I use git and hg for my personal use though I m still a novice at both, but I realize they re much more modern and better, faster, distributed, etc. It s just everyone is so ...

Using Git in a TFS shop

Using Git at home has spoiled me - I now find using TFS at work to be a bit of a drag and want to explore the possibility of using Git locally and syncing somehow with TFS. I figure there are a few ...

热门标签