如何撤消git reset --hard HEAD~1?

Pau*_*cks 1083 git version-control git-reset

是否可以撤消由以下命令引起的更改?如果是这样,怎么样?

git reset --hard HEAD~1
Run Code Online (Sandbox Code Playgroud)

Bri*_*man 1632

Pat Notz是对的.只要在几天之内,您就可以获得提交.除非你明确告诉它删除更新的blob,否则git只会在大约一个月后收集垃圾.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file
Run Code Online (Sandbox Code Playgroud)

您可以在示例中看到file2因硬重置而被删除,但是当我通过reflog重置时,它被放回原位.

  • 你可以使用"git reset --hard HEAD @ {1}",不需要使用SHA1.在大多数情况下,使用"git reset --hard ORIG_HEAD"就足够了. (205认同)
  • 这有一个非常重要的警告......那就是" - 硬"部分.--hard会吹走你当地未提交的更改.你不能让他们这样回来(因为他们没有在任何地方承诺).我相信你无能为力:( (54认同)
  • `git log -g`可以比`git reflog`更好地查看reflog. (35认同)
  • 你是一个救星。 (6认同)
  • 我更喜欢`git reflog`而不是`git log -g`只是因为你在一行上获得了sha1,HEAD信息和提交消息的所有信息.更容易阅读. (5认同)
  • `恢复丢失的更改:`如果您通过`git reset --hard`意外丢失了未提交的更改,您仍然可以从编辑器恢复丢失的更改。只需转到丢失更改的文件,然后按“ctrl-z”即可撤消到硬重置之前的状态。非常明显的方法,但有时却没有想到。现代编辑器还拥有所有更改历史记录,您可以从中获取更改。 (4认同)
  • ^只是因为你知道你可以在重置之前存储你的本地更改 - 硬件,然后只是弹出它们而你什么都不会丢失!得爱git. (2认同)

Pat*_*otz 352

您要做的是指定要还原到的提交的sha1.您可以通过检查reflog(git reflog)然后执行来获取sha1

git reset --hard <sha1 of desired commit>

但是不要等待太久......几周之后,git最终会将提交视为未引用并删除所有blob.

  • **几分钟前我自己的警告**:这将重置所有修改.但它不会触及未跟踪的文件. (2认同)

小智 159

答案隐藏在上面的详细回复中,您可以简单地做到:

$> git reset --hard HEAD@{1}
Run Code Online (Sandbox Code Playgroud)

(参见git reflog show的输出)

  • 请注意,如果您在重置后进行了任何其他repo更改,则这不是解决方案.在运行任何东西之前,一定要看一下reflog. (14认同)
  • 为什么这不是公认的答案? (3认同)
  • 意外重置了我的存储库,以为我的工作永远丢失了。这个答案救了我一天。 (2认同)

sve*_*joh 102

如果Git尚未收集垃圾,则可以恢复它.

通过以下方式获取悬挂提交的概述fsck:

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
Run Code Online (Sandbox Code Playgroud)

使用rebase恢复悬空提交:

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
Run Code Online (Sandbox Code Playgroud)

  • 你保存了我最近6天的工作.谢谢. (8认同)
  • 那是很棒的东西。救了生命。 (2认同)
  • 详细说明可以在这里找到:https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c。救生的东西。 (2认同)

Chr*_*ris 42

如果你真的很幸运,就像我一样,你可以回到文本编辑器并点击"撤消".

我知道这不是一个正确的答案,但它为我节省了半天的工作,所以希望它能为其他人做同样的事情!

  • 这是在硬重置后恢复文件中未分级更改的唯一方法.也救了我;) (8认同)
  • 作为一个额外的提示,一些IDE作为eclipse也保存了最近的文件历史记录.这样,您甚至可以在编辑器关闭后恢复较旧的更改.这给我带来了奇迹. (4认同)
  • 并感谢你们在这整个世界中所有的善良.谢谢.谢谢.谢谢. (3认同)
  • 这实际上是一个非常好的提示,为我节省了很多次;)它的方式比在git中做任何事情都简单... (2认同)
  • 很好,很好的建议,对于 IntelliJ 系列(例如 PhpStorm、WebStorm、RubyMine、PyCharm),您可以右键单击文件名并选择“本地历史记录 &gt; 显示历史记录”,也可以以这种方式恢复。假设 IDE 已打开并跟踪本地更改。 (2认同)

suh*_*lvs 36

据我所知,--hard将丢弃未提交的更改.因为这些不是由git跟踪的.但你可以撤消discarded commit.

$ git reflog
Run Code Online (Sandbox Code Playgroud)

将列出:

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....
Run Code Online (Sandbox Code Playgroud)

这里4bac331discarded commit.

现在只需将头移至该提交::

$ git reset --hard 4bac331
Run Code Online (Sandbox Code Playgroud)

  • 你救了我免于被解雇 (6认同)

Sti*_*and 33

IRL案例:

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one
Run Code Online (Sandbox Code Playgroud)

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <stian@Stians-Mac-mini.local>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*
Run Code Online (Sandbox Code Playgroud)

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.
Run Code Online (Sandbox Code Playgroud)

  • **晃动的斑点**听起来像是AD&D怪物! (2认同)

Aje*_*i32 28

在大多数情况下,是的.

根据运行命令时存储库所处的状态,效果git reset --hard可以从简单到撤消,到基本上不可能.

下面我列出了一系列不同的可能方案,以及如何从中恢复.

我的所有更改都已提交,但现在提交已经消失!

当您git reset使用参数运行时,通常会发生这种情况,如git reset --hard HEAD~.别担心,这很容易恢复!

如果你刚刚跑步git reset并且之后没有做任何其他事情,你可以回到这个单线的位置:

git reset --hard @{1}
Run Code Online (Sandbox Code Playgroud)

这会将当前分支重置为上次修改之前的状态(在您的情况下,对分支的最新修改将是您尝试撤消的硬重置).

但是,如果你已经做出其他修改,因为重置您的分支,一个班轮以上将无法正常工作.相反,您应该运行以查看对您的分支所做的所有最近更改的列表(包括重置).该列表看起来像这样:git reflog <branchname>

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit
Run Code Online (Sandbox Code Playgroud)

在此列表中找到要"撤消"的操作.在上面的例子中,它将是第一行,即"重置:移动到HEAD~".然后该操作之前(下面)复制提交的表示.在我们的例子中,那将是master@{1}(或者3ae5027,它们都代表相同的提交),并运行git reset --hard <commit>以将当前分支重置回该提交.

我上演了我的变化git add,但从未承诺过.现在我的变化消失了!

恢复起来有点棘手.git 确实包含您添加的文件的副本,但由于这些副本从未绑定到任何特定提交,因此您无法一次性恢复所有更改.相反,您必须在git的数据库中找到各个文件并手动恢复它们.你可以使用git fsck.

有关详细信息,请参阅在暂存区域中使用未提交的文件撤消git reset --hard.

我对工作目录中的文件进行了更改,我从未上过该文件git add,并且从未提交过.现在我的变化消失了!

哦,哦.我不想告诉你这个,但你可能运气不好.git不存储您未添加或提交的更改,并且根据以下文档git reset:

- 硬

重置索引和工作树.之后对工作树中跟踪文件的任何更改<commit>都将被丢弃.

可能可以使用某种磁盘恢复实用程序或专业数据恢复服务来恢复更改,但此时可能比它的价值更麻烦.


Jör*_*tag 20

如果您还没有垃圾收集您的存储库(例如使用git repack -dgit gc,但请注意垃圾收集也可以自动发生),那么您的提交仍然存在 - 它不再可以通过HEAD访问.

您可以通过查看输出来尝试查找您的提交git fsck --lost-found.

较新版本的Git有一个称为"reflog"的东西,它是对refs所做的所有更改的日志(与对存储库内容所做的更改相反).因此,例如,每次切换HEAD(即每次执行git checkout切换分支)时都会记录.当然,你git reset也操纵了HEAD,所以它也被记录了.您可以访问您的裁判旧州中,你可以访问你的仓库的旧的状态类似的方式,通过使用@符号代替~,像git reset HEAD@{1}.

我花了一段时间来理解HEAD @ {1}和HEAD~1之间的区别,所以这里有一点解释:

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog
Run Code Online (Sandbox Code Playgroud)

因此,HEAD~1意味着"在HEAD当前指向的提交之前转到提交",同时HEAD@{1}意味着"在它指向当前指向的位置之前转到HEAD指向的提交".

这将很容易让您找到丢失的提交并恢复它.

  • 我认为另一种解释会更清楚:HEAD~1意味着去"HEAD的父母",而HEAD @ {1}则去"HEAD历史中的一步" (2认同)

New*_*yte 18

如果您使用的是 JetBrains IDE(任何基于 IntelliJ 的),您甚至可以通过其“本地历史记录”功能恢复您未提交的更改。

右键单击文件树中的顶级目录,在上下文菜单中找到“本地历史记录”,然后选择“显示历史记录”。这将打开一个视图,您可以在其中找到您最近的编辑,一旦找到要返回的修订,右键单击它并单击“还原”。


Cod*_*ard 12

在回答之前,我们添加一些背景,解释这是什么HEAD.

First of all what is HEAD?

HEAD只是对当前分支上当前提交(最新)的引用.在任何给定时间
只能有一个HEAD.(不包括git worktree)

内容HEAD存储在内部.git/HEAD,它包含当前提交的40字节SHA-1.


detached HEAD

如果你没有进行最新的提交 - 意味着HEAD指向历史记录中的先前提交,则调用它detached HEAD.

在此输入图像描述

在命令行上它看起来像这样 - SHA-1而不是分支名称,因为HEAD它没有指向当前分支的尖端

在此输入图像描述


关于如何从分离的HEAD中恢复的几个选项:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back
Run Code Online (Sandbox Code Playgroud)

这将检查指向所需提交的新分支.
此命令将签出到给定的提交.
此时,您可以创建一个分支,并从此开始工作.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>
Run Code Online (Sandbox Code Playgroud)

git reflog

你总是可以使用它reflog.
git reflog将显示更新的任何更改,HEAD并检出所需的reflog条目将设置HEAD回此提交.

每次修改HEAD时,都会有一个新条目 reflog

git reflog
git checkout HEAD@{...}
Run Code Online (Sandbox Code Playgroud)

这将使您回到所需的提交

在此输入图像描述


git reset HEAD --hard <commit_id>

"移动"你的头回到所需的提交.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
Run Code Online (Sandbox Code Playgroud)
  • 注意:( 自Git 2.7起)
    您也可以使用它git rebase --no-autostash.


git revert <sha-1>

"撤消"给定的提交或提交范围.
reset命令将"撤消"给定提交中所做的任何更改.
将提交具有撤消补丁的新提交,而原始提交也将保留在历史记录中.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>
Run Code Online (Sandbox Code Playgroud)

此模式说明了哪个命令执行的操作.
正如你所看到的那样reset && checkout修改了HEAD.

在此输入图像描述


小智 11

我知道这是一个老线程...但是由于许多人正在寻找在Git中撤消内容的方法,我仍然认为继续在这里给出提示可能是一个好主意.

当你在git gui中执行"git add"或从左上角到左下角移动任何内容时,文件的内容将存储在blob中,文件内容可以从该blob中恢复.

因此即使文件未提交也可以恢复文件,但必须添加文件.

git init  
echo hello >> test.txt  
git add test.txt  
Run Code Online (Sandbox Code Playgroud)

现在blob已创建,但它被索引引用,因此在我们重置之前不会使用git fsck列出.所以我们重置......

git reset --hard  
git fsck  
Run Code Online (Sandbox Code Playgroud)

你会得到一个悬垂的blob ce013625030ba8dba906f756967f9e9ca394464a

git show ce01362  
Run Code Online (Sandbox Code Playgroud)

会给你文件内容"你好"回来

为了找到未引用的提交,我在某个地方发现了一个建议.

gitk --all $(git log -g --pretty=format:%h)  
Run Code Online (Sandbox Code Playgroud)

我把它作为git gui中的工具,它非常方便.


neu*_*ron 5

制作了一个小脚本,以便更容易地找到正在寻找的提交:

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

是的,用 awk 或类似的东西可以让它变得相当漂亮,但它很简单,我只是需要它。可能会为其他人节省 30 秒。


Mac*_*ski 5

我刚刚对错误的项目进行了硬重置。救了我一命的是 Eclipse 的当地历史。据说 IntelliJ Idea 也有,你的编辑器也有,值得一看:

  1. 关于本地历史的 Eclipse 帮助主题
  2. http://wiki.eclipse.org/FAQ_Where_is_the_workspace_local_history_stored%3F


Sco*_*des 5

git reflog

  • 在列表中找到您的提交,然后将其复制并粘贴到以下命令中:

git cherry-pick <the sha>

  • 效果很好。你救了我的命! (4认同)
  • 就是这样,你拯救了我的一天 (3认同)
  • 当每个人搜索如何撤消硬重置更改时,实际上都在寻找这一点。这个答案应该得到更多的支持 (2认同)

归档时间:

查看次数:

384269 次

最近记录:

6 年 前