我不小心将错误的文件提交给Git,但尚未将提交推送到服务器。
如何从本地存储库撤消这些提交?
唯一的方法似乎是在某种 GUI 文本编辑器中复制编辑,然后擦除整个本地克隆,然后重新克隆存储库,然后重新应用编辑。然而,
git commit
有没有更好的办法?
$ git commit -m "Something terribly misguided" # (0: Your Accident) $ git reset HEAD~ # (1) [ edit files as necessary ] # (2) $ git add . # (3) $ git commit -c ORIG_HEAD # (4)
git add
reset
.git/ORIG_HEAD
commit
-c ORIG_HEAD
-C
或者,要编辑先前的提交(或仅编辑其提交消息),commit --amend会将当前索引内的更改添加到先前的提交。
commit --amend
要删除(而不是还原)已推送到服务器的提交,必须使用重写历史记录git push origin master --force。
git push origin master --force
上面的答案将向您显示git reflog,您可以使用它来确定要还原到的提交的 SHA-1。获得此值后,请使用上述命令序列。
git reflog
如果您不知道它是如何工作的,那么撤消提交有点可怕。但是,如果您确实理解,它实际上非常容易。我将向您展示可以撤消提交的 4 种不同方式。
git reset --hard
假设您有这个,其中 C 是您的 HEAD, (F) 是您的文件状态。
(F) A-B-C ↑ master
您想取消提交 C 并且再也看不到它并丢失本地修改文件中的所有更改。你做这个:
git reset --hard HEAD~1
结果是:
(F) A-B ↑ master
现在 B 是 HEAD。因为您使用了--hard,您的文件将重置为提交 B 时的状态。
--hard
git reset
啊,但假设提交 C 不是一场灾难,只是有点偏离。您想撤消提交,但在进行更好的提交之前保留您的更改以进行一些编辑。从这里重新开始,以 C 为您的 HEAD:
您可以执行此操作,而无需执行以下操作--hard:
git reset HEAD~1
在这种情况下,结果是:
在这两种情况下, HEAD 只是指向最新提交的指针。当你执行 a 时git reset HEAD~1,你告诉 Git 将 HEAD 指针移回一次提交。但是(除非您使用--hard),您将文件保持原样。所以现在git status显示您已签入 C 的更改。您没有丢失任何东西!
git status
git reset --soft
对于最轻的接触,您甚至可以撤消您的提交,但保留您的文件和索引:
git reset --soft HEAD~1
这不仅让您的文件独自一人,它甚至让您的索引独自一人。当你这样做时git status,你会看到索引中的文件和以前一样。事实上,在这个命令之后,你可以这样做,git commit并且你会重做你刚才所做的同样的提交。
还有一件事:假设您像第一个示例中那样销毁提交,但后来发现您毕竟需要它?运气不好,对吧?
不行,还是有办法找回来的。键入git reflog,您将看到您移动的(部分)提交shas(即哈希)列表。找到您销毁的提交,然后执行以下操作:
git checkout -b someNewBranchName shaYouDestroyed
你现在已经恢复了那个提交。提交在 Git 中实际上不会在大约 90 天内被销毁,因此您通常可以返回并拯救一个您不想摆脱的。