在Git存储库中查找和恢复已删除的文件

说我在Git仓库。 我删除一个文件并提交更改。 我继续工作,做更多的承诺。 然后,我发现我需要恢复该文件。

我知道我可以使用git checkout HEAD^ foo.bar来签出一个文件,但是我不知道该文件何时被删除。

  1. find删除给定文件名的提交最快的方法是什么?
  2. 将该文件恢复到我的工作副本最简单的方法是什么?

我希望我不必手动浏览我的日志,签出一个给定的SHA整个项目,然后手动将该文件复制到我原来的项目结帐。

find影响给定path的最后一个提交。 由于该文件不在HEAD提交中,因此该提交必须将其删除。

 git rev-list -n 1 HEAD -- <file_path> 

然后使用脱字符号( ^ )符号检出之前提交的版本:

 git checkout <deleting_commit>^ -- <file_path> 

或者在一个命令中,如果$file是有问题的文件。

 git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file" 
  1. 使用git log --diff-filter=D --summary获取删除文件和删除文件的所有提交;
  2. 使用git checkout $commit~1 filename来恢复被删除的文件。

要恢复文件夹中所有已删除的文件,请input以下命令。

 git ls-files -d | xargs git checkout -- 

如果你疯了,使用git-bisect 。 这是做什么:

 git bisect start git bisect bad git bisect good <some commit where you know the file existed> 

现在是时候运行自动化testing了。 如果存在foo.bar ,shell命令'[ -e foo.bar ]'将返回0,否则返回1。 git-bisect的“run”命令将使用二进制search来自动查找testing失败的第一个提交。 它从给定的范围(从好到坏)开始中途,根据指定的testing结果将其减半。

 git bisect run '[ -e foo.bar ]' 

现在你在删除它的提交。 从这里开始,你可以跳回到将来,用git-revert来取消这个改变,

 git bisect reset git revert <the offending commit> 

或者您可以返回一个提交并手动检查损坏情况:

 git checkout HEAD^ cp foo.bar /tmp git bisect reset cp /tmp/foo.bar . 

我来到这个问题寻找恢复我刚刚删除的文件,但我还没有承诺的变化。 万一你发现自己处在这种情况下,你只需要做以下事情:

git checkout HEAD -- path/to/file.ext

我最喜欢的别名,基于bonyiii的回答 (upvoted)和我自己的回答:“ 传递参数给Git别名命令 ”:

 git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f' 

我已经丢失了一个文件,在几次提交之前被误删了?
快:

 git restore my_deleted_file 

危机避免了。


罗伯特·戴利 在评论中提出了以下别名:

 restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1" 

而jegan补充说 :

为了从命令行设置别名,我使用了这个命令:

 git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

恢复已删除并提交的文件:

 git reset HEAD some/path git checkout -- some/path 

它在Git版本1.7.5.4上进行了testing。

如果你知道文件名,这是一个简单的方法与基本的命令:

列出该文件的所有提交。

 git log -- path/to/file 

最后一个提交(最上面)是删除文件的提交。 所以你需要恢复第二个到最后一个提交。

 git checkout {second to last commit} -- path/to/file 

我有这个解决scheme 。

  1. 使用以下某种方法获取文件被删除的提交的ID。

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* git log --stat | grep --context=5 *word* #如果你几乎不记得任何东西,
  2. 你应该得到像这样的东西:

提交bfe68bd117e1091c96d2976c99b3bcc8310bebe7作者:Alexander Orlovdate:四月12日星期四23:44:27 2011 +0200

 replaced deprecated GWT class - gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script 

提交3ea4e3af253ac6fd1691ff6bb89c964f54802302作者:Alexander Orlovdate:四月12日星期四22:10:22 2011 +0200

3 。 现在使用提交ID bfe68bd117e1091c96d2976c99b3bcc8310bebe7做:

 git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java 

由于提交ID引用文件已经被删除的提交,你需要引用在bfe68b之前的提交,你可以通过追加^1 。 这意味着:在bfe68b之前给我提交。

如果您只做了更改并删除了一个文件,但没有提交,现在您已经与您的更改分手了

 git checkout -- . 

但你删除的文件没有返回,你只需要执行下面的命令:

 git checkout <file_path> 

而且,你的文件又回来了。

 git checkout /path/to/deleted.file 

在许多情况下,将coreutils (grep,sed等)与Git结合使用会非常有用。 我已经很了解这些工具,但Git不那么重要。 如果我想要search已删除的文件,我会执行以下操作:

 git log --raw | grep -B 30 $'D\t.*deleted_file.c' 

当我find修订/提交时:

 git checkout <rev>^ -- path/to/refound/deleted_file.c 

就像其他人在我之前所说的一样。

该文件现在将恢复到删除之前的状态。 如果你想保留它,记得重新提交到工作树。

git undelete path/to/file.ext

  1. 把它放在你的.bash_profile (或者打开一个命令shell时加载的其他相关文件)中:

     git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -' 
  2. 然后使用:

     git undelete path/to/file.ext 

这个别名首先检查find这个文件存在的最后一个提交,然后从该文件存在的最后一个提交执行该文件path的git检出。 资源

所以我不得不从一个特定的提交恢复一堆已删除的文件,我用两个命令来pipe理它:

 git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(注意每个命令末尾的尾部空格。)

这些文件已被添加到.gitignore文件,然后用git rm清除,我需要恢复文件,但是然后取消它们。 我有数百个文件要恢复,为每个文件手动input的东西,如在其他例子将是太慢了。

在我们的例子中,我们意外地删除了一个提交中的文件,稍后我们意识到我们的错误,并希望找回所有被删除的文件,但不是那些被修改的文件。

基于查尔斯·贝利的优秀答案,这里是我的一个class轮:

 git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2) 
 user@bsd:~/work/git$ rm slides.tex user@bsd:~/work/git$ git pull Already up-to-date. user@bsd:~/work/git$ ls slides.tex ls: slides.tex: No such file or directory 

还原已删除的文件:

 user@bsd:~/work/git$ git checkout D .slides.tex.swp D slides.tex user@bsd:~/work/git$ git checkout slides.tex user@bsd:~/work/git$ ls slides.tex slides.tex 

如果您知道删除文件的提交,请运行此命令,其中<SHA1_deletion>是删除该文件的提交:

 git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 -- 

pipe道之前的部分列出了在提交中被删除的所有文件; 他们都是从以前的提交结算,以恢复他们。

如果您遇到这个问题的频率更高,而且您愿意使用Git GUI工具,请查看DeepGit并在其中使用File | Search