关于版本控制:执行git reset后恢复添加的文件–hard HEAD ^

Recovering added file after doing git reset --hard HEAD^

我添加了一个新文件f1并对另一个文件f2进行了更改,但随后执行了一个"git reset--hard head^",并丢失了对该文件的所有更改。

有什么办法吗,我可以把它们拿回来。

我在这里看到了一个相关的问题:我如何才能撤消Git重置——硬头~1?但是,这个问题假设已经完成了Git提交。


您可以(通过一些工作)在最后一次"git add"时恢复文件的状态。你可以使用

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

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

请阅读git fsck手册页。


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

  • 获取git知道文件名的不可访问文件列表:

    1
    2
    3
    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
  • 如果您看到一些有趣的内容,git cat-file blob SHA-1-of-interesting-file将把文件输出到标准输出。(示例:git cat-file blob b8f0bdf56 > recovered-logo.png)

  • 不幸的是,如果丢失的文件不是任何提交的一部分,那么git就没有时间戳,因此,您不能按时间打印不同版本的文件。

    如果丢失的文件从未被转移(git stagegit add或隐藏(git stash),你就不太走运了,因为据Git所知,该文件从未存在过。(你还可以试着做一个git fsck --no-reflogs --lost-found,在.git/lost-found/other目录中四处看看,看看你是否有什么值得保存的东西,以防Git确实有一份你丢失的文件的副本,因为一些幸运的事故。在这种情况下,您没有文件名来帮助您,只有文件内容。)

    如果您刚刚丢失了一些提交(而不是文件),那么您可能需要运行类似这样的程序:

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

    这将运行gitk,包括所有分支、所有回流和所有悬而未决的承诺。如果您的repo有很多提交(比如Linux内核),您可能需要添加-n 10000或其他一些限制。如果没有gitk,您可以只使用如下命令行运行较低版本:

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

    或者输出不太详细的版本

    1
    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


    有一个git plugin可以实现这一点:

    https://github.com/pendashteh/git-recover-索引

    1
    2
    3
    $ cd /path/to/disatered/repo
    $ git clone [email protected]:pendashteh/git-recover-index.git $HOME/.git-recover-index
    $ $HOME/.git-recover-index/git-recover-index.sh

    请尝试以下操作:http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html

    我因为失去的改变而心脏病发作。但在跟踪这篇文章之后。我把零钱拿回来了


    实际上,如果您已经将对象添加到索引中(通过使用git add),则会为该对象的状态创建一个blob—但是没有引用它的树(因此,提交)对象。这就是如何获得一个"悬空"的松散对象文件,如果运行git fsck,它将向您显示未引用的blob(如果运行git gc,它将删除这些类型的对象)。

    因此,如果启用了reflog,则可以使用它来尝试恢复已添加文件f1的索引状态。如果你根本没有添加F2,那么就像格雷格说的那样,Git对它一无所知,你在那里就走运了。