撤消git重置 - 登台区域中没有任何不满的文件

发布于 2025-01-24 12:31:47 字数 462 浏览 10 评论 0原文

我正在努力恢复我的工作。我愚蠢地做了git reset -hard,但是在此之前,我只完成了获取添加。,并且不做git commit。请帮忙!这是我的日志:

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

在这种情况下,是否有可能撤消git重置 - hard

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

灯下孤影 2025-01-31 12:31:48

我刚刚进行了git重置-Hard,然后丢失了一个提交。但是我知道提交哈希,所以我能够做git cherry-pick commit_hash来还原它。

我在失去该提交的几分钟之内就这样做了,因此它可能对你们中的一些人有用。

I just did a git reset --hard and lost one commit. But I knew the commit hash, so I was able to do git cherry-pick COMMIT_HASH to restore it.

I did this within a few minutes of losing the commit, so it may work for some of you.

别理我 2025-01-31 12:31:48

感谢Mark Longair,我得到了我的东西!

首先,我将所有哈希保存到一个文件中:

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

接下来,我将它们全部放入列表中,然后将数据全部放入新文件中...您必须选择您的文件并将其重命名,然后重命名它们。需要...但是我只需要几个文件..希望这可以帮助某人...

commits = ["c2520e04839c05505ef17f985a49ffd42809f",
    "41901be74651829d97f29934f190055ae4e93",
    "50f078c937f07b508a1a73d3566a822927a57",
    "51077d43a3ed6333c8a3616412c9b3b0fb6d4",
    "56e290dc0aaa20e64702357b340d397213cb",
    "5b731d988cfb24500842ec5df84d3e1950c87",
    "9c438e09cf759bf84e109a2f0c18520",
    ...
    ]

from subprocess import call
filename = "file"
i = 1
for c in commits:
    f = open(filename + str(i),"wb")
    call(["git", "show", c],stdout=f)
    i+=1

Thanks to Mark Longair I got my stuff back!

First I saved all the hashes into a file:

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

next I put them all (removing the 'unreachable blob' thing) in a list and put the data all in new files...you have to pick your files and rename them again which you need...but I only needed a few files..hope this helps someone...

commits = ["c2520e04839c05505ef17f985a49ffd42809f",
    "41901be74651829d97f29934f190055ae4e93",
    "50f078c937f07b508a1a73d3566a822927a57",
    "51077d43a3ed6333c8a3616412c9b3b0fb6d4",
    "56e290dc0aaa20e64702357b340d397213cb",
    "5b731d988cfb24500842ec5df84d3e1950c87",
    "9c438e09cf759bf84e109a2f0c18520",
    ...
    ]

from subprocess import call
filename = "file"
i = 1
for c in commits:
    f = open(filename + str(i),"wb")
    call(["git", "show", c],stdout=f)
    i+=1
绾颜 2025-01-31 12:31:48

在这种情况下, @ajedi32的评论解决方案对我有用。

git reset --hard @{1}

请注意,所有这些解决方案都依赖没有GIT GC,其中一些可能会导致一个解决方案,因此我会在尝试任何内容之前将您的.git目录的内容汇总,以便您有一个快照可以返回为您工作。

@Ajedi32's solution in the comments worked for me in exactly this situation.

git reset --hard @{1}

Note that all these solutions rely on there being no git gc, and some of them might cause one, so I'd zip up the contents of your .git directory before trying anything so that you have a snapshot to go back to if one doesn't work for you.

开始看清了 2025-01-31 12:31:48

遇到了同一问题,但没有将更改添加到索引中。因此,上面的所有命令都没有带给我所需的更改。

毕竟,这是一个幼稚的提示,但可能会像我一样拯救一个没有先考虑一下的人。

在绝望中,我试图在每个打开选项卡中按CTRL-Z(LightTable)中的CTRL-Z - 幸运的是,这在该选项卡中恢复了该文件,然后在git reset-reset-Hard之前恢复了其最新状态。 。

Ran into the same issue, but had not added the changes to the index. So all commands above didn't bring me back the desired changes.

After all the above elaborate answers, this is a naive hint, but may be it'll save someone who didn't thought about it first, as I did.

In despair, I tried to press CTRL-Z in my editor (LightTable), once in every open tab — this luckily recovered the file in that tab, to its latest state before the git reset --hard.

述情 2025-01-31 12:31:48

天哪,我拉了头发,直到遇到这个问题及其答案。我相信,只有将上面的两个评论拉在一起时,对问问题的正确和简洁的答案才可用,所以这里全部位于一个地方:

  1. chilicuil提到,运行git reflog在那里识别
    您想回到

    的提交哈希

  2. Akimsko提到的提交哈希,您可能不想樱桃挑选
    除非您只丢失了一个提交,否则您应该运行git重置 - hard&lt; hash-commit-you-want&gt;

for egit eclipse用户:我找不到一种方法用Egit进入Eclipse的步骤。关闭Eclipse,从终端窗口上方运行上面的命令,然后重新打开Eclipse对我来说很好。

Goodness, I pulled my hair until I ran into this question and its answers. I believe the correct and succinct answer to the question asked is only available if you pull two of the comments above together so here it is all in one place:

  1. As mentioned by chilicuil, run git reflog to identify in there the
    commit hash that you want to get back to

  2. As mentioned by akimsko, you will likely NOT want to cherry pick
    unless you only lost one commit, so you should then run git reset --hard <hash-commit-you-want>

Note for egit Eclipse users: I couldn't find a way to do these steps within Eclipse with egit. Closing Eclipse, running the commands above from a terminal window, and then reopening Eclipse worked just fine for me.

谁的新欢旧爱 2025-01-31 12:31:48

如果您使用IDE编辑文件,则可能还可以将其自身的历史记录独立于git。在某些情况下,完全绕过git并使用IDE要简单得多。例如,Intellij Idea和Eclipse都具有这种自动化的本地版本控制,它们称为“本地历史”。在Intellij中,可以直接检索许多文件中的一批丢失的更改:在项目窗格中,您可以右键单击整个项目或目录树,然后选择“本地历史记录”子菜单中的显示历史记录。 git reset-- hard应以“外部更改”(即从IDE外部触发)出现在列表中,您可以使用“还原”按钮或上下文菜单项将所有内容都恢复到状态就在发生外部变化之前。

If you are editing your files with an IDE, it may also be keeping its own history independent of Git. In some circumstances it is much simpler to bypass Git entirely and use the IDE. For example, IntelliJ IDEA and Eclipse both have this kind of automated local version control, which they refer to as "local history". In IntelliJ it's straightforward to retrieve a whole batch of lost changes across many files: in the Project pane, you can right-click an entire project or directory tree and select Show History in the Local History submenu. The git reset --hard should appear in the list as an "external change" (i.e. triggered from outside the IDE), and you can use the revert button or context menu item to revert everything to the state right before that external change happened.

我做我的改变 2025-01-31 12:31:48

对于那里的GIT专业人员来说,这可能是显而易见的,但是我想提出这一点,因为在我疯狂的搜索中,我没有看到这种情况。

我上演了一些文件,并进行了git重置 - hard,吓坏了一点,然后注意到我的状态显示了我所有的文件仍在上演,并且所有删除​​所有删除都没有上演。

在这一点上,只要您不进行他们的删除,您就可以进行那些分阶段的更改。
之后,您只需要勇于努力进行git重置 - hard又一次,这将使您回到您上演的那些更改,现在刚刚承诺。

同样,这对大多数人来说可能并不新鲜,但是我希望这对我有帮助,而且我没有发现任何暗示这一点,所以它可能会对其他人有所帮助。

This is probably obvious to the git professionals out there, but I wanted to put it up since in my frantic searching I didn't see this brought up.

I staged some files, and did a git reset --hard, freaked out a little, and then noticed that my status showed all my files still staged as well as all their deletions unstaged.

At this point you can commit those staged changes, as long as you don't stage their deletions.
After this, you only have to work up the courage to do git reset --hard one more time, which will bring you back to those changes you had staged and now just committed.

Again, this is probably nothing new to most, but I'm hoping that since it helped me and I didn't find anything suggesting this, it might help someone else.

本宫微胖 2025-01-31 12:31:48

如果您最近查看了git diff,那么还有另一种方法可以从这样的事件中恢复,即使您还没有上演更改:如果git git diff 仍在控制台缓冲区中,您可以滚动,将差异复制到文件中,然后使用patch工具将差异应用于树:patch -patch -p0&lt;文件。这种方法为我节省了几次。

If you've recently reviewed a git diff then there's another way to recover from incidents like this, even when you haven't staged the changes yet: if the output of git diff is still in your console buffer, you can just scroll up, copy-paste the diff into a file and use the patch tool to apply the diff to your tree: patch -p0 < file. This approach saved me a few times.

花间憩 2025-01-31 12:31:48

但是,上述解决方案可能起作用,但是,有更简单的方法可以从中恢复过来
这不是通过git -s复杂的撤消。我猜最多
git-resets发生在少数文件上,如果您已经使用了vim,则
可能是最耗时的解决方案。警告是你已经必须
使用vim的 persistent-undo,您应该使用两种方式,因为
它为您提供了消除无限数量更改的能力。

以下是:

  1. 在vim中按:键入命令设置dudodir。如果您有持续
    在您的.vimrc中启动
    ,它将显示与类似的结果
    undodir =〜/.vim_runtime/temp_dirs/dododir

  2. 在您的回购中使用git log以查找最后的日期/时间
    提交

  3. 使用dudodir使用
    cd〜/.vim_runtime/temp_dirs/undodir

  4. 在此目录中使用此命令来查找您拥有的所有文件
    自上次提交以来改变了


    寻找 。 -Newermt“ 2018-03-20 11:24:44” \! -newermt“ 2018-03-23” \(-type f
    -regextype posix -extended -regex'。*'\)\ - not -path'*/env/*” - not -path -path
    “*/。git/*”

    在这里“ 2018-03-20 11:24:44”是上次提交的日期和时间。如果是
    您进行git重置的日期-Hard是“ 2018-03-22”,然后使用
    “ 2018-03-22”,然后使用“ 2018-03-23”。这是因为发现的怪癖,
    下边界是包容性的,上限是独家的。
    https://unix.stac.stackexchange.com/a/a/70404/242983

  5. https://unix.stac.stackexchange.com/a/70404/242983 文件在VIM中打开它们,然后进行“较早的20m”。
    您可以通过使用“ h之前”找到有关“较早”的更多详细信息。这里
    早期20m是指20分钟前返回文件状态,
    假设您在20分钟后进行了git -reset。重复一遍
    find命令中删除的所有文件。我相信
    有人可以编写一个将这些内容结合在一起的脚本。

The above solutions may work, however, there are simpler ways to recover from
this instead of going through git-s complex undo. I would guess that most
git-resets happen on a small number of files, and if you already use VIM, this
might be the most time-efficient solution. The caveat is that you already must
be using ViM's persistent-undo, which you should be using either way, because
it provides you the ability to undo unlimited number of changes.

Here are the steps:

  1. In vim press : and type the command set undodir. If you have persistent
    undo
    turned on in your .vimrc, it will show a result similar to
    undodir=~/.vim_runtime/temp_dirs/undodir.

  2. In your repo use git log to find out the last date/time you made the last
    commit

  3. In your shell navigate to your undodir using
    cd ~/.vim_runtime/temp_dirs/undodir.

  4. In this directory use this command to find all the files that you have
    changed since the last commit


    find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f
    -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path
    "*/.git/*"

    Here "2018-03-20 11:24:44" is the date and time of the last commit. If the
    date on which you did the git reset --hard is "2018-03-22", then use
    "2018-03-22", then use "2018-03-23". This is because of a quirk of find,
    where the lower boundary is inclusive, and the upper bound is exclusive.
    https://unix.stackexchange.com/a/70404/242983

  5. Next go to each of the files open them up in vim, and do a "earlier 20m".
    You can find more details about "earlier" by using "h earlier". Here
    earlier 20m mean go back to the state of the file 20 minutes back,
    assuming that you did the git hard --reset, 20 mins back. Repeat this over
    all the files that was spitted out from the find command. I am sure
    somebody can write a script that will combine these things.

得不到的就毁灭 2025-01-31 12:31:48

我正在使用Intellij,并且能够简单地浏览每个文件并进行:

edit-&gt;从磁盘重新加载

幸运的是,我刚刚完成了git状态,然后才能消除工作更改,因此我确切地知道我必须重新加载的内容。

I'm using IntelliJ and was able to simply go through each file and do:

Edit -> reload from disk

Luckily, I had just done a git status right before I wiped out my working changes, so I knew exactly what I had to reload.

信愁 2025-01-31 12:31:48

我无法使用git命令恢复文件。就我而言,这是一个CPP文件。我知道其中一个独特的字符串, this 帮助了。命令是:

sudo grep -a -B[number of rows before the text being searched] -A[number of rows after the text being searched] '[some unique text in the lost file]' /dev/sda3 > test.cpp

搜索整个磁盘,但最终找到了丢失文件的内容。

I was not able to recover the file using git commands. In my case, it was a CPP file. I knew a unique string in it and this helped. The command is:

sudo grep -a -B[number of rows before the text being searched] -A[number of rows after the text being searched] '[some unique text in the lost file]' /dev/sda3 > test.cpp

Searches the whole disk but in the end, it found the content of the lost file.

潦草背影 2025-01-31 12:31:48

记住您的文件层次结构并使用Mark Longair进行Phil Oakley修改的技术会产生巨大的结果。

从本质上讲,如果您至少将文件添加到存储库中但不承诺,则可以通过使用git show进行交互恢复,检查日志并使用shell重定向来创建每个文件(记住您的感兴趣的路径) 。

Remembering your file hierarchy and using the technique of Mark Longair with Phil Oakley modification yields dramatic results.

Essentially if you at least added the files to the repo but not committed it, you can restore by interactively using git show, inspect the log and use shell redirection to create each file (remembering your path of interest).

说谎友 2025-01-31 12:31:48

使用Intellij Idea的本地历史功能

我也处于类似情况,但没有承诺的更改,并且没有添加到索引(git add。),我成功地 恢复了它。

如果您使用的是Intellij Idea,请按照以下步骤:

  • 在Intellij Idea中,转到项目视图。 (文件夹图标左上角
  • 右键单击文件或目录中丢失更改的目录。
  • 从上下文菜单中选择“本地历史”。
  • 从子菜单中选择“显示历史”。
  • 这将显示对文件或目录进行的本地更改的列表,包括丢失的更改。然后,您可以选择要还原的版本并将其恢复到它。
  • 右键单击选定的版本,然后单击“还原”,

这将恢复您的未承诺的更改。

Recover your uncommitted changes using IntelliJ IDEA's local history feature

I was also in the similar situation but with uncommitted changes and also wasn't added to index (git add .), I successfully recovered it.

If you're using IntelliJ IDEA, please follow the below steps:

  • In IntelliJ IDEA, go to the project view. (Folder icon on the top left bar)
  • Right-click on the file or directory where you lost the changes.
  • Choose "Local History" from the context menu.
  • From the submenu, select "Show History".
  • This will display a list of local changes made to the file or directory, including the lost changes. You can then select the version you want to restore and revert to it.
  • Right-click on the selected version then click "Revert"

This will revert back your uncommitted changes.

春花秋月 2025-01-31 12:31:47

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

但是,我在测试存储库上尝试了一下,并且有一些问题 - - cached应该是- cache ,我发现它实际上并未创建.git/oftost-found目录。但是,以下步骤对我有用:

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

该步骤应在对象数据库中输出所有参考,索引中或通过reflog无法触及的对象。输出看起来像这样:

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

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

git show 907b308

输出文件的内容。


输出太多?

响应 sehe 在下面的评论:

从该命令中列出的树中列出的树,您可能需要从未参考提交中引用的任何对象中删除任何对象。 (通常您可以通过反射仪回到这些提交 - 我们只是对已添加到索引但永远无法通过提交的对象感兴趣。)

首先,保存命令的输出,现在:

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

现在可以找到这些无法到达的提交的对象名称:

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/对象下考虑最近修改的文件。您可以使用以下方式找到这些信息:(

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

我发现查找 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

请注意,您必须在路径末端删除/以获取对象名称。 )

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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文