如何撤消git reset --hard HEAD〜1?
是否可以撤消以下命令引起的更改?如果是这样,怎么办?
git reset --hard HEAD~1
解决方案
回答
我们要做的是指定要还原到的提交的sha1. 我们可以通过检查reflog(git reflog
)来获取sha1,然后执行
git reset --hard <所需提交的sha1>
但是不要等待太久...几周后git最终会将该提交视为未引用并删除所有blob。
回答
Pat Notz是正确的。只要几天之内就可以收回承诺。 git仅在大约一个月左右后进行垃圾收集,除非我们明确告诉它删除较新的blob。
$ 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重置时,该文件又恢复了原位。
回答
如果Git尚未进行垃圾回收,则可以恢复它。
使用fsck
获取悬空提交的概述:
$ git fsck --lost-found dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
使用rebase恢复悬空的提交:
$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
回答
如果我们尚未对存储库进行垃圾回收(例如,使用git repack -d
或者git gc
,但请注意垃圾回收也可以自动进行),那么提交仍然存在吗?它只是无法通过HEAD到达。
我们可以通过查看git fsck --lost-found的输出来尝试查找提交。
较新版本的Git具有称为" reflog"的内容,它是对ref所做的所有更改(与对存储库内容所做的更改相反)的日志。因此,例如,每次切换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
因此,HEAD〜1
的意思是"在HEAD当前指向的提交之前转到提交",而HEAD @ {1}的意思是"在HEAD指向当前指向的提交之前指向的提交。 "。
这样可以轻松地找到丢失的提交并进行恢复。