你完成了一次简单的提交 git 操作,但经过一些推送前的检查,发现存在很多问题,需要重新修改,需要撤消此次操作。如果,你是一个很熟悉 git 操作的人来说,这很简单,反之,希望你能好好看看此文。
git 中的 head 与本地文件的关系
HEAD 是当前分支引用的指针,它总是指向某次commit,默认是上一次的commit。 这表示 HEAD 将是下一次提交的父结点。 通常,可以把 HEAD 看做你的上一次提交的快照。当然HEAD的指向是可以改变的,比如你提交了commit,切换了仓库,分支,或者回滚了版本,切换了tag等。
从这一点来看,head 和本地文件的状态可以说存在千丝万缕关系,但,我们不能说,head 的指针指向的文件状态和当前文件的状态一致,这得取决于你每一次的 git 操作。为方便说明,作以下假设:
假设你有这个,其中 C 是你的 HEAD,(F)是你的文件的状态。A、B 都是之前的提交状态。
(F)
A-B-C
↑
master
现在有以下几种撤销 C 提交的方案可以选择:
- 在撤销 C 提交后,保留 C 提交时的文件状态
- 在撤销 C 提交后,不保留 C 提交时的文件状态
方案一:git reset --hard
由于 C 提交方案彻底错误,无需在原文件上继续修改,需要回到某个提交状态下,才能继续修改,故在撤销 C 提交后,不保留 C 提交时的文件状态,如下:
(F)
A-B
↑
master
操作方法:git reset --hard HEAD~1
方案二:git reset --soft
或许,C 提交方案并不是完全不可取,而是需要在其现有基础上进行修改,但并不需要保留过多提交的中间过程,所以需要回退到某次提交版本,并保留当前文件状态,即在撤销 C 提交后,不保留 C 提交时的文件状态。如下:
(F)
A-B-C
↑
master
操作方法: git reset --soft
补救措施
如果,进行撤销操作后,又发现,其实 C 提交也有可取之处,需要回退此次提交,那该怎么办呢?
- 查找提交的所有提交修改记录的哈希ID:
git reflog
- 恢复了该提交::
git checkout -b someNewBranchName shaYouDestroyed
注:提交实际上不会在大约 90 天内在 Git 中被销毁,因此通常可以返回并挽救一个不想删除的提交。