我不小心将错误的文件提交给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
with-c ORIG_HEAD
将打开一个编辑器,它最初包含来自旧提交的日志消息,并允许您对其进行编辑。如果您不需要编辑消息,则可以使用该-C
选项。或者,要编辑先前的提交(或仅编辑其提交消息),commit --amend
会将当前索引内的更改添加到先前的提交。
要删除(而不是还原)已推送到服务器的提交,必须使用重写历史记录git push origin master --force
。
上面的答案将向您显示git reflog
,您可以使用它来确定要还原到的提交的 SHA-1。获得此值后,请使用上述命令序列。
如果您不知道它是如何工作的,那么撤消提交有点可怕。但是,如果您确实理解,它实际上非常容易。我将向您展示可以撤消提交的 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 时的状态。
git reset
啊,但假设提交 C 不是一场灾难,只是有点偏离。您想撤消提交,但在进行更好的提交之前保留您的更改以进行一些编辑。从这里重新开始,以 C 为您的 HEAD:
(F)
A-B-C
↑
master
您可以执行此操作,而无需执行以下操作--hard
:
git reset HEAD~1
在这种情况下,结果是:
(F)
A-B-C
↑
master
在这两种情况下, HEAD 只是指向最新提交的指针。当你执行 a 时git reset HEAD~1
,你告诉 Git 将 HEAD 指针移回一次提交。但是(除非您使用--hard
),您将文件保持原样。所以现在git status
显示您已签入 C 的更改。您没有丢失任何东西!
git reset --soft
对于最轻的接触,您甚至可以撤消您的提交,但保留您的文件和索引:
git reset --soft HEAD~1
这不仅让您的文件独自一人,它甚至让您的索引独自一人。当你这样做时git status
,你会看到索引中的文件和以前一样。事实上,在这个命令之后,你可以这样做,git commit
并且你会重做你刚才所做的同样的提交。
git reset --hard
并且需要取回该代码还有一件事:假设您像第一个示例中那样销毁提交,但后来发现您毕竟需要它?运气不好,对吧?
不行,还是有办法找回来的。键入git reflog
,您将看到您移动的(部分)提交shas(即哈希)列表。找到您销毁的提交,然后执行以下操作:
git checkout -b someNewBranchName shaYouDestroyed
你现在已经恢复了那个提交。提交在 Git 中实际上不会在大约 90 天内被销毁,因此您通常可以返回并拯救一个您不想摆脱的。