Git: How to find a deleted file in the project commit history?
从前,我的项目中有一个文件,我现在想能够得到。
问题是:我不知道什么时候删除了它,它在哪条路径上。
当这个文件存在时,我如何定位它的提交?
- 这里有类似的问题:stackoverflow.com/questions/7093602/…
- 在git中删除文件时可能会重复find
- 这里的答案对我比副本中的答案更有用。
- 同意……不管是重复的……他们在谷歌搜索中没有出现……这个……我希望我们不要再浪费时间追寻重复的东西了……只有时间,谷歌的算法才能知道哪一个问题是最好的。
如果您不知道可以使用的确切路径
1
| git log --all --full-history -- **/thefile.* |
如果知道文件的路径,可以执行以下操作:
1
| git log --all --full-history -- <path-to-file> |
这应该显示所有接触该文件的分支中的提交列表。然后,您可以找到所需文件的版本,并用…
1
| git show <SHA> -- <path-to-file> |
或者用以下方法将其还原到您的工作副本中:
git checkout ^ --
请注意插入符号(^在标识的签出之前获得签出,因为在提交文件时,文件被删除,我们需要查看上一个提交以获得已删除文件的内容。
- 尝试使用相对路径而不是绝对路径(如果您还没有)。
- 如果你不知道确切的路径怎么办?你只知道文件名吗?
- @牧师回答了另一个问题
- @牧师:stackoverflow.com/questions/6017987/&hellip;
- 旁注:你的路径必须使用'/'而不是'''花了我一整天的时间才弄明白:/
- 恢复命令不起作用,请参阅下面的akshay agarwal答案。
- @当您在一个文件从未存在的分支上时,pedromoretrolo git log -- 将没有输出。您应该始终使用git log --all -- ,以确保不会错过在其他分支上发生的更改。如果您有多个分支,并且倾向于忘记路径和分支(如我),那么命令git log -- 可能非常危险;如果您与其他开发人员一起工作,那么它也很危险。
- @Amber,考虑在你的git log答案中添加--all(谢谢Philip),这样人们就不会错过其他分支的更改和文件。它会让像我这样健忘的人省去很多悲伤。
- 如下面的答案所述,恢复文件应该是git checkout ^ -- (注意^符号),因为在提交文件时,文件被删除了,我们需要查看上一次提交以获取删除文件的内容。
- @kipeloves假定您使用的是删除提交的sha,而不是所需文件版本的sha。
- @Kipeloves我不明白为什么^是必要的。为什么要在最后一个拥有文件的哈希之后选择哈希?
- 当使用**/thefile.*时,引用它通常是一个好主意,例如'**/thefile.*'来保护global *不受外壳的影响。(我不熟悉windows shell,当它们吃了*的时候,但是如果在bash中当前的工作目录中有一个意外的匹配,那可能会造成麻烦。)
- 这对我不起作用,命令什么也不返回,但第二大投票答案起作用。
- 我运行了命令git log --all -- ,它确实提供了文件的一些历史:添加和更改文件时。但它不会在移动或删除文件时显示提交。上述讨论中未涉及的任何情况?
- 确保将目录更改为git项目的根目录。在使用子目录中的命令时,相对路径有问题
- 文件名区分大小写。很好地为Windows用户了解命令通常不存在的地方。
- 不适用于Git 2.7.4+鱼壳。如果你有这个组合,卡拉夫给出的另一个答案。
- 这对我来说很敏感…
- 当我运行第一个命令时,它列表提交与删除的文件无关。
- 将--stat添加到git log命令中,以实际查看返回提交中修改的文件。
获取已删除文件的列表并复制已删除文件的完整路径
1
| git log --diff-filter=D --summary | grep delete |
执行下一个命令以查找该提交的提交ID并复制提交ID
1
| git log --all -- FILEPATH |
显示已删除文件的差异
1
| git show COMMIT_ID -- FILE_PATH |
记住,您可以使用>之类的工具将输出写入文件。
1
| git show COMMIT_ID -- FILE_PATH > deleted.diff |
- 这是一个令人惊奇和全面的答案!我不知道你能像这样把日志结果反馈给grep。
- 虽然我在第一步的帮助下找到了路径,但第二步却抛出了这个错误:unknown revision or path not in the working tree。
- 要查看提交散列和删除,可以执行git log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'。
- 步骤2不返回任何内容。你知道为什么会这样吗?我的文件名是正确的。
- 要找到将这三个函数组合成一个函数,请将其添加到.bashrc或.zshrc:git-grep-latest(){ result_path=$(git log --diff-filter=D --summary | grep $1 | head -1 | awk '{print $4;}'); latest_commit=$(git log --all -- $result_path | head -1 | awk '{print $2;}'); git show $latest_commit -- $result_path; }中,现在只需执行:git-grep-latest some_text即可。
- git log --name-only --diff-filter=D --pretty=format: | awk 'NF'是imo的第一个命令(打印repo中所有现在已删除的文件)的一个更干净的选择。
- 或者直接获取所有删除文件的提交哈希:git log --name-only --diff-filter=D --format="%H%b"。
- @tylerjones你可以使用管道(google EDOCX1)(6)向Linux提供任何东西。你会喜欢的。
无法编辑已接受的响应,因此在此处将其添加为答案,
要在git中恢复文件,请使用以下命令(注意sha后面的"^"符号)
1
| git checkout <SHA>^ -- /path/to/file |
- 我不明白你为什么想要^。文件正和那个sha一起提交……为什么要从那里返回另一个提交?
- 它在提交中,sha被"删除",这意味着它仍然不存在。在那之前,你必须先提交,才能真正把它恢复过来。
- @tandrewnichols,这意味着你使用了错误的commit sha-你想要为你想要的文件版本进行commit…可能不是删除文件的版本。
- @琥珀色和您想要的提交很可能是它被删除之前的最新提交,因此这个答案。
- 感谢您的^提示^。在窗户里要当心,它需要双引号。
- @Alexr:~1应该是一样的,不需要用引号括起来。
假设您想要恢复一个名为MyFile的文件,但它的路径(或扩展名)不确定:
prelim.:通过单步执行git根来避免混淆
一个重要的项目可能有多个同名或相同的目录。
找到完整的路径
git log --diff-filter=D --summary | grep delete | grep MyFile
delete mode 100644 full/path/to/MyFile.js
full/path/to/MyFile.js是您要查找的路径和文件。
确定影响该文件的所有提交
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.
签出文件
如果选择第一个列出的提交(按时间顺序最后一个提交,这里是bd8374c),将找不到该文件,因为该文件已在该提交中删除。
1 2 3
| > git checkout bd8374c -- full/path/to/MyFile.js
`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.` |
只需选择前面的(附加插入符号)提交:
1
| > git checkout bd8374c^ -- full/path/to/MyFile.js |
@琥珀给出了正确的答案!只需再添加一个,如果您不知道文件的确切路径,可以使用通配符!这对我很有用。
1
| git log --all -- **/thefile.* |
- 谢谢。我在答案中加了这个。
- @佩德罗莫特罗罗,嗯,我不知道我对把现有答案复制到最有投票权的答案有什么感觉:这个答案本身也很有用;一个赞成票可能就足够了?
- imho这是为读者提供最佳结果的方法。
- 如果文件在项目根目录中(在cygwin中测试),则找不到该文件。
这里的一个烦人的事情是获取已删除文件的路径,所以我只写了一个简单的命令,在这里一个dev或git用户可以传递一个已删除的文件名并获取历史记录:
1
| git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- |
如果有人,可以改进指挥,请做。
- 太棒了,谢谢!看起来我的档案根本就不存在,但这是一个单独的问题,而且要复杂得多…
尝试使用其中一个查看器,如gitk,这样您就可以浏览历史记录,找到记忆不足的文件。(如果所有分支机构都需要,使用gitk --all)
- --all选项对您的答案和接受的答案都至关重要。
- 浏览历史对于大多数项目来说需要花费大量的时间。
总结:
步骤1
在已删除文件的历史记录中搜索文件的完整路径git log --diff-filter=D --summary | grep filename。
步骤2
您可以在删除文件之前将其从提交中还原
1 2 3 4 5 6 7 8
| 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"
gco $last_commit^ -- $filepath
}
restore my/file_path |