1.Git工作区原理图
要清楚理解git reset的三个模式的区别,首先应该搞明白Git的各个工作区的划分。
工作区(working directory):在当前仓库中,新增,更改,删除文件这些动作,都发生在工作区里面。可简单理解为正在编辑的本地工程。
暂存区(英文叫stage或index):它实际上就是一个包含文件索引的目录树,像是一个虚拟的工作区。在这个虚拟工作区的目录树中,记录了文件名、文件的状态信息(时间戳、文件长度等),文件的内容并不存储其中,而是保存在Git对象库(.git/objects)中,文件索引建立了文件和对象库中对象实体之间的对应。如果当前仓库,有文件更新,并且使用git add 命令,那么这些更新就会出现在暂存区中。
版本库:当前仓库下,如果没有任何的提交,那么版本库就是对应上次提交后的内容。
下图可以清晰解释三者的关系:
从上图可以看出各个git指令与各工作区的关系。
2.Git撤销指令与工作区关系实践
2.1 git rm --cached:将文件从Index中移除
首先在项目中创建一个aaa.txt文件。此时aaa.txt只存在于工作区(working directory)。使用git status查看文件状态:
使用 git add指令将aaa,txt提交到暂存区Index,此时工作区与暂存区已同步。使用git status查看文件状态:
此时如果想要将aaa.txt文件从Index中移除,只保留在工作区中,可以使用git rm --cached指令。
git add的作用是将工作区新增的文件添加到暂存区中,也可以将工作区已经被Trace文件的改动同步到暂存区中
可以发现执行git rm --cached指令后,aaa.txt从Index中移除,只保存在工作区。
2.2 git reset
将aaa.txt文件重新add到Index暂存区,然后执行commit操作将aaa.txt提交到版本库。如果此时想要撤销commit,可以进行如下操作:
git reset --soft HEAD~1, 执行后再查看status如下:
可以看出,执行完git reset --soft HEAD~1后aaa.txt变成待commit状态,即aaa.txt在工作区与暂存区中保留,版本库已回滚。
重新执行commit后,执行git reset --mixed HEAD~1操作:
执行git reset --mixed HEAD~1操作后,此时aaa.txt处于待add状态,即aaa.txt保留在了工作区,暂存区与版本库中已回滚。
重新执行commit -add后,执行git reset --hard HEAD~1操作:
此时aaa.txt在工作区,暂存区,版本库中均已回滚。
注意:使用reset操作后,在git log中的commit记录也会被删除。
2.3 git revert
相比于reset操作会修改commit history,git revert
命令通过创建一次新的 commit
来撤销一次 commit
所做出的修改。这种撤销的方式是安全的,因为它并不修改commitm history。