撤消git reset - 在暂存区域中使用未提交的文件 [英] Undo git reset --hard with uncommitted files in the staging area

查看:198
本文介绍了撤消git reset - 在暂存区域中使用未提交的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图恢复我的工作。我愚蠢地做了 git reset --hard ,但在此之前我只完成了 get add。并且没有做 git commit 。请帮忙!这是我的日志:

  MacBookPro:api用户$ git status 
#分支主
#更改要提交:
#(使用git reset HEAD< file> ...来取消)

#修改:.gitignore
...


MacBookPro:api user $ git reset --hard
HEAD现在在ff546fa为api添加了新的结构

在这种情况下,是否可以撤消 git reset --hard

解决方案

您应该能够恢复添加到索引中的任何文件(例如,在您的情况下,使用 git add。),尽管它可能有点工作。为了向索引添加文件,git将它添加到对象数据库中,这意味着只要垃圾收集尚未发生,就可以恢复它。有一个如何在中给出的示例JakubNarębski的答案在这里:



然而,我在一个测试版本库中试过,并且出现了一些问题 - - cached 应该是 - -cache ,我发现它实际上并没有创建 .git / lost-found 目录。但是,以下步骤适用于我:

  git fsck --cache --unreachable $(git for-each-ref  - -format =%(objectname))

这应该输出对象数据库中的所有对象,任何参考资料,索引中或通过reflog均无法访问。输出结果如下所示:

 无法访问的blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3 
无法访问的blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

...对于每个斑点,您都可以这样做:

  git show 907b308 

输出文件内容






输出太多了吗?



sehe 的评论如下:



如果您发现在该命令的输出中列出了许多提交和树,则可能希望从输出中除去未引用提交引用的任何对象。 (通常你可以通过reflog回到这些提交 - 我们只是对已经添加到索引中的对象感兴趣,但是不能通过提交找到它。)

首先,保存命令的输出:

  git fsck --cache --unreachable $(git for -each-ref --format =%(objectname))>所有

现在可以找到那些无法访问的提交的对象名称:

  egrep commit all | cut -d''-f 3 

所以你可以找到刚添加的树和对象到索引,但没有承诺任何一点,与:

  git fsck --cache --unreachable $(git for- each-ref --format =%(objectname))\ 
$(egrep commit all | cut -d''-f 3)

这极大地减少了您必须考虑的对象数量。






更新:下面的 Philip Oakley 暗示了另一种减少要考虑的对象数量,它只考虑 .git / objects 下最近修改的文件。你可以找到这些:

  find .git / objects / -type f -printf'%TY-%Tm-%Td %TT%p \ n'| (code> find > invocation 这个列表的结尾可能如下所示:

  2011-08-22 11:43:43.0234896770 .git / objects / b2 / 1700b09c0bc0fc848f67dd751a9e4ea5b4133b 
2011-09-13 07:36:37.5868133260 .git / objects / de / 629830603289ef159268f443da79968360913a

在这种情况下,您可以看到这些对象:

  git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b 
git show de629830603289ef159268f443da79968360913a

(请注意,您必须移除路径末尾的 / 以获取对象名称。)


I am trying to recover my work. I stupidly did git reset --hard, but before that I've done only get add . and didn't do git commit. Please help! Here is my log:

MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)

#   modified:   .gitignore
...


MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api

Is it possible to undo git reset --hard in this situation?

解决方案

You should be able to recover any files back that you added to the index (e.g, as in your situation, with git add .) although it might be a bit of work. In order to add a file to the index, git adds it to the object database, which means it can be recovered so long as garbage collection hasn't happened yet. There's an example of how to do this given in Jakub Narębski's answer here:

However, I tried that out on a test repository, and there were a couple of problems - --cached should be --cache, and I found that it didn't actually create the .git/lost-found directory. However, the following steps worked for me:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")

That should output all objects in the object database that aren't reachable by any ref, in the index, or via the reflog. The output will look something like this:

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

... and for each of those blobs, you can do:

git show 907b308

To output the contents of the file.


Too much output?

Update in response to sehe's comment below:

If you find that you have many commits and trees listed in the output from that command, you may want to remove from the output any objects which are referenced from unreferenced commits. (Typically you can get back to these commits via the reflog anyway - we're just interested in objects that have been added to the index but can never be found via a commit.)

First, save the output of the command, with:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > all

Now the object names of those unreachable commits can be found with:

egrep commit all | cut -d ' ' -f 3

So you can find just the trees and objects that have been added to the index, but not committed at any point, with:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") \
  $(egrep commit all | cut -d ' ' -f 3)

That enormously cuts down the number of objects you'll have to consider.


Update: Philip Oakley below suggests another way of cutting down the number of objects to consider, which is to just consider the most recently modified files under .git/objects. You can find these with:

find .git/objects/ -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort

(I found that find invocation here.) The end of that list might look like:

2011-08-22 11:43:43.0234896770 .git/objects/b2/1700b09c0bc0fc848f67dd751a9e4ea5b4133b
2011-09-13 07:36:37.5868133260 .git/objects/de/629830603289ef159268f443da79968360913a

In which case you can see those objects with:

git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b
git show de629830603289ef159268f443da79968360913a

(Note that you have to remove the / at the end of the path to get the object name.)

这篇关于撤消git reset - 在暂存区域中使用未提交的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆