执行git reset后恢复添加的文件--hard HEAD ^

时间:2009-07-10 10:39:42

标签: git version-control

我添加了一个新文件F1,并对另一个文件F2进行了更改,但随后执行了“git reset --hard HEAD ^”,我丢失了对文件的所有更改。

是否有某种方式,我可以让它们回来。

我确实在这里查看了一个相关的问题:How can I undo git reset --hard HEAD~1?但是,这个问题假定那个人做了一个git提交。

5 个答案:

答案 0 :(得分:97)

您可以(通过一些工作)在最后一个“git add < file> ”恢复文件状态。你可以使用

$ git fsck --cache --no-reflogs --lost-found --unreachable  HEAD

然后检查'.git / lost-found / other'目录中的文件。

请阅读git fsck联机帮助页。

答案 1 :(得分:24)

(我假设丢失的文件是任何提交的一部分。否则,git log --all -g --diff-filter=D --stat是你的朋友。)

  1. 获取git知道文件名的无法访问的文件列表:

    git fsck --unreachable --no-reflogs --no-cache HEAD | fgrep " tree " \
    | cut -d " " -f3 | xargs -r -n1 git ls-tree \
    | fgrep " blob " | cut -d " " -f 3- | sort -k2 -u
    
  2. 如果您看到有趣的内容,git cat-file blob SHA-1-of-interesting-file会将文件输出到标准输出。 (例如:git cat-file blob b8f0bdf56 > recovered-logo.png

  3. 不幸的是,如果丢失的文件不是任何提交的一部分,git没有时间戳,因此,您无法打印按时间排序的各种版本的文件。

    如果丢失的文件从未上过阶段(git stagegit add)或被隐藏(git stash),那么你几乎没有运气,因为就git所知,文件从未存在过。 (您仍然可以尝试执行git fsck --no-reflogs --lost-found并在目录.git/lost-found/other中查看,看看您是否有任何值得保留的内容,以防git确实拥有您遗失的文件的副本,但是您还没有。在这种情况下,文件名可以帮助您,只有文件内容。)

    如果你刚刚丢失了一些提交(而不仅仅是文件),你可能想要运行这样的东西:

    gitk --all $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )
    

    这将运行gitk所有分支,所有reflog和所有悬空提交。如果您的repo有很多提交(比如linux内核),您可能需要添加-n 10000或其他一些限制。如果您没有gitk,则可以仅使用如下命令行运行较小版本:

    git log --all --decorate --stat --graph --date-order $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )
    

    或具有较少详细输出的版本

    git log --all --decorate --oneline --graph --date-order $( git fsck | awk '/dangling commit/ {print $3}'; git log -g --pretty='format:%H' )
    

    如果您看到某些提交要保存为分支recovered1,只需执行git checkout -b recovered1 <sha1-of-the-commit>

答案 2 :(得分:5)

有一个git plugin开箱即用:

https://github.com/pendashteh/git-recover-index

$ cd /path/to/disatered/repo
$ git clone git@github.com:pendashteh/git-recover-index.git $HOME/.git-recover-index
$ $HOME/.git-recover-index/git-recover-index.sh

答案 3 :(得分:4)

实际上,如果你已经将对象添加到索引中(通过使用git add),则会为该对象的状态创建一个blob - 但是没有树(因此,commit)对象引用它。这就是人们获取“悬空”松散目标文件的方法,如果你运行git fsck,它会显示未引用的blob(如果运行git gc会删除这些类型的对象)。

因此,您可以使用reflog(如果已启用它)尝试恢复已添加的文件F1的索引状态。如果你还没有添加F2,那么就像格雷格所说的那样,git对此一无所知,你在那里运气不好。

答案 4 :(得分:4)

试试这个http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html

我因为失去的变化而心脏病发作。但在关注这篇文章之后。我得到了我的更改