如何撤销 'git reset' 操作?

1930

我该如何撤销这个命令?

git reset HEAD~

3
如果有人想知道如何撤销硬重置,请查看撤消 git reset --hard HEAD~1。解决方案非常相似。 - user456814
2
可能是如何撤销git reset --hard HEAD~1?的重复问题。 - underscore_d
6
这不是关于--hard相关问题的重复!意外执行此命令的风险要高得多。例如,您想使用git reset foo-file取消暂存单个文件。您只写了文件名的前半部分,按tab键进行自动完成,它实际上完成了一个分支名称,您没有注意到并运行了git reset foo-branch命令。就这样。 - Yushin Washio
5个回答

3476

简短回答:

git reset 'HEAD@{1}'

长篇回答:

Git会记录所有引用更新的日志(例如:checkout、reset、commit、merge)。您可以通过输入以下命令查看它:

git reflog

在这个列表中有一个丢失的提交。假设你刚刚输入了git reset HEAD~ 并想要撤销它。我的reflog看起来像这样:

$ git reflog
3f6db14 HEAD@{0}: HEAD~: updating HEAD
d27924e HEAD@{1}: checkout: moving from d27924e0fe16776f0d0f1ee2933a0334a4787b4c
[...]

第一行代码表示当前位置(即0个位置之前)为3f6db14,是由重置到HEAD~得到的。第二行代码表示当前位置往前一个位置(即重置前的状态)为d27924e。虽然这个过程中使用了特定的提交,但现在并不重要。因此,要撤销重置,请运行git reset HEAD@{1}(或git reset d27924e)。

另外,如果您在此之后运行了其他命令来更新HEAD,那么您想要的提交可能不在列表顶部,您需要通过reflog进行搜索。

最后注意:查看特定分支(例如master)的reflog可能比查看HEAD更容易找回要撤销的提交。

$ git reflog show master
c24138b master@{0}: merge origin/master: Fast-forward
90a2bf9 master@{1}: merge origin/master: Fast-forward
[...]

这应该比通常的 HEAD reflog 更少噪音。


56
作为比“reflog”更视觉化和更好看的替代品,我喜欢使用“git log --graph --decorate --oneline $(git rev-list -g --all)”来做这个事情。它展示了所有提交的树形结构,包括悬空的未命名分支。 - texasflood
2
假设我有一个包含现有文件的目录。在该目录中,我运行 git init,然后紧接着运行 git reset --hard。没有 reflog,甚至没有任何日志可供参考。这些文件现在基本上已经无法恢复了吗? - AlanSE
3
git reset HEAD~12 --> 撤销最近的12次提交并取消暂存区的更改。 oops... --> 表示出现错误或意外情况。 git reset HEAD@{12} --> 恢复到第12次提交的状态,并取消暂存区的更改。 nooo .. --> 表示不愿意接受或反对某个建议或做法。 'git reflog' to the rescue! --> 使用git reflog命令来找回丢失的提交或分支。 oh it's just git reset HEAD@{1} --> 原来只需要使用git reset HEAD@{1}命令即可。 - Dennis
3
尝试使用“短回答”(复制并粘贴)时,我得到了以下错误:fatal: ambiguous argument ''HEAD@{1}'': unknown revision or path not in the working tree. 通过省略围绕着 HEAD@{1} 的引号解决了这个问题。 - Tom Ladek
1
可以用于撤销 git reset --soft HEAD~1,并且在运行 git reset 'HEAD@{1}' 后,暂存区也是干净的。 - fstang
显示剩余14条评论

340

这是一个老问题,之前发布的答案都很好用。我想提供另外一种选择。

git reset ORIG_HEAD

ORIG_HEAD 是指向之前 HEAD 所指的那个提交。


1
这听起来很不错 - 你能详细说明一下吗?这里的“ORIG”是指“original”还是“origin”?也就是说,它会重置到开始搞乱之前HEAD所在的位置吗?还是重置到源上HEAD所在的位置?如果在git reset ORIG_HEAD之前已经多次移动了HEAD,会发生什么?谢谢。 - Benjohn
1
ORIG代表原始版本,ORIG_HEAD表示重置之前的原始HEAD。 - Sam Gallagher
2
某些操作,例如合并和重置,在调整HEAD到新值之前会将先前版本记录在ORIG_HEAD中。您可以使用ORIG_HEAD来恢复或还原到先前的状态或进行比较。——摘自《Git版本控制》一书。 - Justin
请注意,HEAD@{1}始终是HEAD的先前值,而ORIG_HEAD是选择命令后HEAD的先前值。 - studgeek

149

我的情况稍有不同,我执行了git reset HEAD~三次。

要撤消它,我必须进行以下操作

git reset HEAD@{3}

所以您应该能够做到

git reset HEAD@{N}

但是如果你已经使用了 git reset

git reset HEAD~3

你需要做的事情

git reset HEAD@{1}

{N}代表reflog中的操作数量,正如Mark在评论中指出的那样。


2
接受的选项没有提供向前走的示例 N。一个小时前,我遇到了这样一种情况,我想转发超过1个。尝试使用多个,它起作用了。想在这里添加一下。对于寻找使用git reset HEAD~3撤消重置的人们来说会很有用。 - zainengineer
3
如果有人执行了git reset HEAD3,他可以通过执行git reset HEAD@{3}来快速撤销它,而不需要进入reflog。git reset HEAD3等是常见的情况。 - zainengineer
1
我认为任何看到 {1} / {2} 的人都会意识到这个数字可以是任何修订版本号,而 reflog 命令可以提供给您。同意你关于这些数字在 ~3 / @{3} 中对于任一方向都相同的观点,但并不需要成为一个新答案。 - Clint

81
  1. 使用 git reflog 命令获取所有更新的引用。

  2. git reset <您想要还原的提交的id>


1
这个!你刚刚救了我,伙计! - Yar

43

答案大部分时间有效

git reset 'HEAD@{1}'

答案总是有效的

git reset --hard 'HEAD@{1}'

使用--hard参数会使所有内容保持与之前相同。


救了我的命... - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接