参考

https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E9%87%8D%E7%BD%AE%E6%8F%AD%E5%AF%86

https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified

https://git-scm.com/docs/git-reset

https://www.liaoxuefeng.com/wiki/896043488029600/897013573512192

前言

在使用git的时候,我们一般提倡是不允许回滚。对于问题的追踪和项目的发展历程而言历史记录都是有用的。并且为了节省一点存储空间而丢失宝贵的代码信息是不值当的。但是我们开发中,肯定会遇到特殊情况需要回退。比如确实操作错了一步历史提交,导致仓库混乱污染或是内容丢失,我们需要回退到干净的一次提交,重新操作。

在git等所有的版本管理软件中,删除操作,只是增加一次记录,内容并不会被删掉,我们可以大胆的操作,这也符合版本仓库的逻辑。只有特殊情况才需要真正的删除,做这种操作的时候需要特别注意,因为一旦失误,无法挽回。

从历史记录中删除 参考 https://www.cnblogs.com/studywithallofyou/p/11772684.html https://www.cnblogs.com/studywithallofyou/p/11772844.html

工作流程

要想理解git reset,那么就要搞清楚git仓库管理流程:

git回退之git reset-LMLPHP

我们修改完内容后,这些记录单单是保存在我们本地目录下,也就是工作目录。如果丢了,就是丢了,无法找回。与普通磁盘上的文件一样,除非到回收站找回。

这时,如果运行了add,那么内容就被记录到本地的暂存仓库,也就是index。这时如果删除文件,在暂存区的内容还存在,并没有丢失。

如下图,我们创建了一个文件4,这时文件4在本地。我们add到暂存仓库,然后删掉文件4,我们发现又多了一条记录删除记录,原来的4还存在,我们可以commit。原来的文件4并没有丢失。

git回退之git reset-LMLPHP

运行commit之后,修改的内容就被保存到了仓库,修改了HEAD(HEAD就是指向当前仓库在哪一个提交历史,不特殊修改,都指向最新的一次提交)。这时运行git status发现目录是干净的。git里面需要提交仓库,暂存仓库和本地目录内容都完全一致,才是干净的,任何一个不一致都会有不同的提示。

比如上面的图,提交的仓库中没有文件4,暂存仓库中增加了4,所以显示绿色的提示内容,add了文件但是还没有commit。但是本次又删除了文件,本地目录中的内容与暂存仓库也不一样,所以提示红色的内容,因为算是警告,没有add的内容是会丢失的。

修改

git回退之git reset-LMLPHP

add

git回退之git reset-LMLPHP

commit

git回退之git reset-LMLPHP

git reset的三个选择

理解了上面的流程,就可以理解git reset了。git reset就是分别逆向操作,也就是把HEAD(提交的仓库)回退到一个指定历史,把HEAD、index(暂存仓库)都回退到指定历史,把HEAD、index和本地目录的内容都回退到一个指定历史。

git回退之git reset-LMLPHP

git reset --soft就是把HEAD回退到指定历史。运行后结果如下

git回退之git reset-LMLPHP

也就相当于我们add了修改的文件,本地目录和暂存仓库都已经一致了,就等待commit。如果我们commit,可以再次填写commit记录,也就实现了git commit --amend的功能。

git回退之git reset-LMLPHP

git reset --mixed就是把HEAD和index都回退到指定的历史。这个也是运行git reset不加参数时的默认规则。运行结果如下

git回退之git reset-LMLPHP

相当于我们仅仅修改了文件,还没做任何处理。

git回退之git reset-LMLPHP

git reset --hard这个是把HEAD、index和本地目录的内容都回退到指定的历史记录。做这一步操作的时候一定要小心,最好把所有的内容都提交,并且push到远程或是拷贝一份。因为这个操作会重置本地的内容到一个指定历史。

我们先运行git log,看到有三个提交历史

git回退之git reset-LMLPHP

运行git reset --hard HEAD~

git回退之git reset-LMLPHP

我们发现仓库是干净的,并且原来的3文件没了,运行git log参看

git回退之git reset-LMLPHP

提交的历史记录也没有了。

这次是真的回退到了指定历史,所有的记录都不见了,我们可以开心的(真的吗?)在原来一个干净的分支上继续写代码了。

git reset --hard的后悔药

世上有没有后悔药我不知道,但是git作为一个先进的分布式管理器,却有无限可能。如果你一不小心,脑袋发热,运行了git reset --hard,但是发现不是你想要的,原来的记录也没了。怎么办?大脑瞬间充血,一片空白。不要慌,首先冷静下来,然后运行git reflog,这个命令是告诉你你的每一次对仓库操作的历史记录,如下

git回退之git reset-LMLPHP

看一下最上面的几条,第一条告诉你当前在e86d948这个提交记录,通过reset切换过来的。对照上面的git log,可以发现这个是第二个提交历史,也就是我们git reset --hard HEAD~的时候回退的分支。第二条记录告诉我们当前是fc9fbc6分支,通过reset回退到这个分支的,我们可以参考上面的git log记录,这个就是我们想要回去的分支。好了,有了记录的哈希值,我们只需再运行一次git reset --hard,如下

git回退之git reset-LMLPHP

查看一下git log

git回退之git reset-LMLPHP

回来了。

git不会删除任何已经提交到版本库的内容,除非你非要专门特殊这样做,并且为了再给你一次机会,像git reset这样,就算你明确说明不要了,它也不会立马删除,除非超过一定时间或是你主动运行git gc等操作,把无用的,没有关联的内容删掉。不然,那条记录还是在本地仓库,只不过它没有被载入历史的长河中。

05-11 11:30