曾几何时,我的项目中有一个文件,我现在希望能够得到它。
问题是:我不知道我什么时候删除它以及它在哪条路径上。
当它存在时,如何找到该文件的提交?
如果您不知道可以使用的确切路径
git log --all --full-history -- "**/thefile.*"
如果您知道文件所在的路径,则可以执行以下操作:
git log --all --full-history -- <path-to-file>
这应该显示涉及该文件的所有分支中的提交列表。然后,您可以找到所需文件的版本,并用...显示它
git show <SHA> -- <path-to-file>
或者使用以下命令将其还原到您的工作副本中:
git checkout <SHA>^ -- <path-to-file>
注意插入符号 (^
),它使签出先于 被识别,因为在 <SHA>
提交时文件被删除,我们需要查看上一次提交获取已删除文件的内容
获取已删除文件的列表并复制已删除文件的完整路径
git log --diff-filter=D --summary | grep delete
执行下一条命令以查找该提交的提交 id 并复制提交 id
git log --all -- FILEPATH
显示已删除文件的差异
git show COMMIT_ID -- FILE_PATH
请记住,您可以使用 >
将输出写入文件,例如
git show COMMIT_ID -- FILE_PATH > deleted.diff
unknown revision or path not in the working tree
。
git log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
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
linux pipes
.. 您会喜欢的。
假设您要恢复一个名为 MyFile
的文件,但不确定它的路径(或它的扩展名,就此而言):
初步:通过进入 git root 来避免混淆
一个重要的项目可能有多个具有相似或相同文件名的目录。
> cd <project-root>
找到完整路径 git log --diff-filter=D --summary | grep 删除 | grep MyFile 删除模式 100644 full/path/to/MyFile.js
full/path/to/MyFile.js
是路径 &您正在寻找的文件。
确定影响该文件的所有提交 git log --oneline --follow --full/path/to/MyFile.js bd8374c 一些有用的提交消息 ba8d20e 另一个影响该文件的先前提交消息 cfea812 提交的第一条消息文件出现。签出文件
如果您选择列出的第一个提交(按时间顺序排列的最后一个,此处为 bd8374c),则找不到该文件,因为它在该提交中被删除。
> git checkout bd8374c -- full/path/to/MyFile.js
`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.`
只需选择前面的(附加插入符号)提交:
> git checkout bd8374c^ -- full/path/to/MyFile.js
git log --diff-filter=D --summary | find "delete" | find "MyFile"
和第 3 步,注意散列周围的引号:git checkout "bd8374c^" -- full/path/to/MyFile.js
无法编辑接受的回复,因此在此处将其添加为答案,
要在 git 中恢复文件,请使用以下命令(注意 SHA 后面的 '^' 符号)
git checkout <SHA>^ -- /path/to/file
<SHA>~1
应该可以正常工作,而无需用引号括起来。
@Amber 给出了正确答案!再补充一点,如果您不知道文件的确切路径,您可以使用通配符!这对我有用。
git log --all -- **/thefile.*
下面是一个简单的命令,其中 dev 或 git 用户可以从存储库根目录传递已删除的文件名并获取历史记录:
git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all --
如果有人可以改进命令,请做。
尝试使用其中一个查看器,例如 gitk
,以便您可以浏览历史记录以找到记忆中的一半文件。 (如果所有分支都需要,请使用 gitk --all
)
--all
选项对于您的答案和接受的答案都至关重要。
如果您希望查看所有已删除文件的大小
以及相关的 SHA
git log --all --stat --diff-filter=D --oneline
添加 -p|--patch
以查看内容
git log --all --stat --diff-filter=D -p
要缩小到任何文件,您有两个简单的选择,您可以使用路径规范,也可以通过管道 grep 并搜索文件名。
使用 grep:
git log --all --stat --diff-filter=D --oneline | grep foo
使用路径规范:
git log --all --stat --diff-filter=D --oneline -- '*foo*'
如果您想查看内容,pathspec 可以与 -p|--patch
一起很好地工作:
git log --all --stat --diff-filter=D --oneline --patch -- '*foo*'
如果您知道文件在哪里,您可能也会喜欢这个
git log --all --full-history -- someFileName
概括:
步骤1
您在已删除文件的历史记录中搜索文件完整路径 git log --diff-filter=D --summary | grep filename
第2步
您在删除之前从提交中恢复文件
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
这是我的解决方案:
git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>
git log -- <path>
在您位于文件从未存在的分支上时将没有输出。您应该始终使用git log --all -- <path>
,以确保您不会错过其他分支上发生的更改。如果您有多个分支并且容易忘记路径和分支(如我),命令git log -- <path>
可能非常危险,如果您与其他开发人员一起工作,它也很危险。--all
(感谢 Philip)添加到您的git log
答案中,这样人们就不会错过其他分支上的更改和文件。它会为像我这样健忘的人省去很多悲伤。git checkout <SHA>^ -- <path-to-file>
(注意 ^ 符号),因为在 <SHA> commit 文件被删除了,我们需要查看之前的commit来获取被删除文件的内容**/thefile.*
时,通常最好引用它,例如'**/thefile.*'
,以保护 glob*
免受 shell 的影响。 (我不熟悉 WIndows shell 以及它们何时吃*
,但如果 bash 中的当前工作目录意外匹配,那可能会造成麻烦。)