我怎样才能撤销git reset –hard HEAD〜1?
是否可以撤消由以下命令造成的更改? 如果是这样,怎么样?
git reset --hard HEAD~1
Pat Notz是正确的。 只要几天之内就可以得到提交。 只有垃圾收集大约一个月左右后,除非你明确告诉它删除更新的斑点。
$ 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
您可以在示例中看到,由于硬重置导致file2被删除,但是在通过reflog重置时放回原位。
你想要做的是指定你想恢复的提交sha1。 你可以通过检查reflog( git reflog
)来获取sha1,然后执行
git reset --hard <sha1 of desired commit>
但不要等太久…几个星期后,git将最终看到提交作为未被引用,并删除所有的斑点。
答案隐藏在上面的详细回复中,你可以简单地做:
$> git reset --hard HEAD@{1}
(请参阅git reflog show的输出)
如果Git还没有垃圾回收,可以恢复它。
使用fsck
获取悬挂提交的概述:
$ git fsck --lost-found dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
通过rebase恢复悬挂提交:
$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
如果你真的很幸运,就像我一样,你可以回到你的文本编辑器并点击“撤消”。
我知道这不是一个真正的答案,但它为我节省了半天的工作时间,所以希望它能为别人做同样的事情!
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
$ 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*
$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a
First, rewinding head to replay your work on top of it... Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.
如果你还没有收集你的仓库的垃圾(例如使用git repack -d
或者git gc
,但是请注意垃圾收集也可以自动发生),那么你的提交仍然存在 – 它不能再通过HEAD到达。
您可以通过查看git fsck --lost-found
的输出来尝试find您的提交。
较新版本的Git有一些称为“reflog”的东西,它是对refs进行的所有更改(而不是对存储库内容所做的更改)的日志。 所以,举例来说,每当你切换你的HEAD(即每次你做一个git checkout
来切换分支)时,都会被logging下来。 而且,当然,你的git reset
也可以控制HEAD,所以它也被logging下来。 你可以通过类似的方式访问你的引用的旧状态,通过使用@
符号而不是~
,如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
所以, HEAD~1
表示“在HEAD当前指向的提交之前进行提交”,而HEAD@{1}
表示“在指向它指向的位置前指向HEAD指向的提交”。
这将很容易让你find你丢失的承诺,并恢复它。
据我所知, – --hard
将放弃未经--hard
改变。 由于这些不是由git跟踪的。 但您可以撤消discarded commit
。
$ git reflog
会列出:
b0d059c HEAD@{0}: reset: moving to HEAD~1 4bac331 HEAD@{1}: commit: added level introduction.... ....
其中4bac331
是discarded commit
。
现在只需将头移动到该提交::
$ git reset --hard 4bac331
在大多数情况下,是的。
根据存储库在运行命令时所处的状态, git reset --hard
的作用可能从简单到撤消,基本上是不可能的。
下面我列出了一系列不同的可能的情况,以及如何从中恢复。
我的所有修改都已经完成,但现在这个提交已经完成了!
这种情况通常发生在你使用参数运行git reset
的时候,例如git reset --hard HEAD~
。 别担心,这很容易从中恢复!
如果你只是运行git reset
而没有做任何其他的事情,那么你可以回到你所在的位置:
git reset --hard @{1}
这会重置您当前的分支,无论上次修改前的状态如何(在您的情况下,对分支的最新修改将是您要恢复的硬重置)。
但是,如果自复位以来您对分行进行了其他修改,则上面的一行将不起作用。 相反,你应该运行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
find您想要“撤消”的列表中的操作。 在上面的例子中,这将是第一行,即“reset:moving to HEAD〜”。 然后复制该操作之前 (之下)的提交表示。 在我们的例子中,这将是master@{1}
(或者3ae5027
,它们都表示相同的提交),然后运行git reset --hard <commit>
将当前分支重置为该提交。
我使用git add
进行了更改,但从未提交过。 现在我的变化消失了!
这从恢复有点棘手。 git 确实有你添加的文件的副本,但由于这些副本从来没有绑定到任何特定的提交,你不能一次恢复所有的更改。 相反,你必须find个人文件在git的数据库中,并手动恢复它们。 你可以使用git fsck
来做到这一点。
有关详细信息,请参阅撤销git reset – 在暂存区域中提交未提交的文件 。
我对我的工作目录中的文件进行了更改,我从未使用git add
,并且从未提交过。 现在我的变化消失了!
呃哦。 我不想告诉你这件事,但你可能倒霉。 git不会存储您不添加或提交的更改,并根据git reset
的文档 :
– 硬
重置索引和工作树。 丢弃自从
<commit>
之后对工作树中跟踪文件所做的任何更改。
您可能可以使用某种磁盘恢复实用程序或专业的数据恢复服务来恢复您的更改,但在这一点上,这可能比它的价值更麻烦。
我知道这是一个古老的线程…但是,许多人正在寻找方法来撤销Git中的东西,我仍然认为在这里继续提供技巧可能是一个好主意。
当你在git gui里做一个“git add”或者从左上angular到左下angular的任何东西时,文件的内容都被存储在一个blob中,并且文件内容可以从该blob中恢复。
所以即使没有提交,也可以恢复文件,但是必须添加文件。
git init echo hello >> test.txt git add test.txt
现在blob被创build,但它被索引引用,所以它不会被列在git fsck中,直到我们重置。 所以我们重置…
git reset --hard git fsck
你会得到一个悬而未决的blob ce013625030ba8dba906f756967f9e9ca394464a
git show ce01362
会给你的文件内容“你好”回来
为了find未提交的提交,我发现了一个提示这个提示。
gitk --all $(git log -g --pretty=format:%h)
我把它作为git gui的一个工具,非常方便。
制作一个小脚本,使其更容易find正在寻找的提交:
git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'
是的,用awk或类似的东西可以使它变得相当漂亮,但它很简单,我只是需要它。 可以保存别人30秒。
我刚刚对错误的项目进行了重置。 Eclipse的本地历史是什么拯救了我的生命。 据说IntelliJ Idea也有一个,你的编辑也是这样,值得检查一下: