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




git攻略 (16)

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

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

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

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存储库中。 我删除了一个文件并提交了更改。 我继续工作,并做了一些更多的提交。 然后,我发现我需要恢复该文件。

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

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

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


查找影响给定路径的最后一次提交。 由于该文件不在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"

如果您使用zsh并启用了EXTENDED_GLOB选项,则插入符号将不起作用。 您可以使用~1代替。

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"

如果您知道文件名,这是使用基本命令的简单方法:

列出该文件的所有提交。

git log -- path/to/file

最后一次提交(最顶层)是删除文件的提交。 所以你需要恢复倒数第二次提交。

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

$ git log --diff-filter=D --summary  | grep "delete" | sort

我来到这个问题寻找恢复我刚删除的文件,但我还没有提交更改。 如果您发现自己处于这种情况,您需要做的就是以下内容:

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


我有这个解决方案

  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 Orlov日期:2011年5月12日星期四23:44:27 +0200

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

commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302作者:Alexander Orlov日期:2011年5月12日22:10:22 +0200

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

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

由于提交id引用了已经删除文件的提交,因此您需要在bfe68b之前引用提交,您可以通过附加^1来执行提交。 这意味着:在bfe68b之前给我提交。


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
    

此别名首先检查以查找此文件存在的最后一次提交,然后从该文件存在的最后一次提交执行该文件路径的git检出。 source


所以我不得不从特定的提交中恢复一堆已删除的文件,并使用两个命令进行管理:

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清除,我需要恢复文件,然后取消它们。 我有几百个要恢复的文件,为每个文件手动输入内容,因为在其他示例中这将太慢。


在我们的例子中,我们意外地删除了提交中的文件,稍后我们意识到了我们的错误,并希望找回所有已删除但未修改的文件。

根据Charles Bailey的优秀答案,这是我的一个班轮:

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)

我有同样的问题。 在不知情的情况下,我创造了一个悬空的提交

列出悬空提交

git fsck --lost-found

检查每个悬挂的提交

git reset --hard <commit id>

当我转向悬空提交时,我的文件重新出现。

git status原因如下:

“HEAD detached from <commit id where it detached>”


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

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

当我找到修订/提交时:

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

就像其他人在我面前所说的那样。

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


简单而精确 -

首先,获取最新的稳定提交,其中您拥有该文件 -

git log 

假设您找到$ commitid 1234567 ...,然后

git checkout <$commitid> $fileName

这将恢复该提交中的文件版本。


如果您只进行了更改并删除了一个文件,但没有提交,那么现在您就分手了

git checkout -- .

但是您删除的文件没有返回,您只需执行以下命令:

git checkout <file_path>

而且,你的档案又回来了。



要还原已删除和已提交的文件:

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

它在Git 1.7.5.4版本上进行了测试。


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

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

危机避免了。

Robert Dailey 在评论中提出以下别名:

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-checkout