从指针行为理解Git中的reset操作

从指针行为理解Git中的reset操作

节点状态

先确立一个状态概念,也就是工作区暂存区工作树上的节点N看作一组状态

当commit之后,状态得以固定:

  • 工作区内容固定为为commit时的内容,如第二次提交时,工作区内容固定为

    bash 复制代码
    第二次提交
  • 暂存区被"清空"(简单理解为被提交到节点上去了,自然就不需要暂存了。)

  • HEAD指向被创建的节点

至此,HEAD以及HEAD之前的节点的状态都可以被确定,之后对工作区和暂存区的更改,我们可以将其看作是对一个未被创建的虚拟节点------待存节点状态的操作

假设第N个(N<=3)固定状态对应的内容:

  • 工作区:第N次提交
  • 暂存区:空
  • 节点:第N次提交

此时,我们对代存节点的状态(工作区和暂存区)进行修改(在1.txt中输入文字):

  1. 修改工作区内容: 第4次提交
  2. 提交到暂存区:git add .,此时暂存区内容也为第4次提交
  3. 再次修改工作区内容: 第5次提交

在git插件中我们可以看到如下情况:

于是现在待存节点的状态可以看作:

将这个状态当作我们实验的初始状态,然后我们就可以来看看使用三种不同的reset方法时到底发生了什么

--hard

bash 复制代码
git reset --hard C2
//c725740f0a4... 第二次提交id,简化为C2

此时可以发现:

  • 工作区:第二次提交 (无显示状态)
  • 暂存区:没有内容
  • HEAD指向C2

而这个恰好是C2的状态!

先不着急得出结论,不妨把剩下的运行结果全部看完

--soft

回到我们的初始状态,然后

bash 复制代码
git reset --soft C2

神奇的事情发生了!

工作区与暂存区的内容不仅没有更改,甚至连状态都没有改变,与初始状态一模一样!

  • 工作区:第五次提交 (M,已修改)
  • 暂存区:第四次提交 (M,已修改)
  • HEAD指向C2

这样看来,虽然节点对应的状态是唯一 的,但是工作区、暂存区、HEAD的变化并不是统一

我们可以为其分别设置三个虚拟指针,来探究到底发生了什么

  • 工作区:HEAD_Work
  • 暂存区:HEAD_Index
  • 节点:自然是HEAD

看到这里或许大家内心都已经有了猜想,我们不妨再来看看最后一个操作验证一下

--mixed

可以确定的是,reset后HEAD是必然改变的(有点像废话。。),有区别的是:

  • 工作区:HEAD_Work
  • 暂存区:HEAD_Index

这两个指针是如何变化的?

从上述内容的表现来看,--hard和--soft分别代表两个极端,一个是全都跟着HEAD变,一个是都不变,那么很容易猜想到--mixed就是改变其中一个,那么这个猜想是否正确?改变的又是哪一个呢?为什么

猜想验证

回到初始状态

bash 复制代码
git reset --mixed C2

可以看到:

  • 工作区:第五次提交 (M,已修改)
  • 暂存区:空
  • HEAD指向C2

猜想得到验证!

指针变化

  • 工作区:HEAD_Work不变
  • 暂存区:HEAD_Index跟着HEAD变
  • 节点:指向C2

为什么是改变暂存区的指针而不是工作区的指针?(猜想)

想象这样一个场景:

你辛辛苦苦写好了一段代码放在工作区,突然发现当前的版本不兼容,而你知道你的代码经过微调后,C2是兼容的,于是你想要回退到C2,但是代码已经写好了,如果用--hard,工作区指针也指向C2,你写的代码将被清除,白忙活一场;如果用--soft,暂存区的指针不改变,虽然不影响后续,但其实没啥必要,恰好,--mixed就实现了这个功能:回退版本,不改变你的代码,清空暂存区,perfect!

这也是为什么--mixed成为了git reset的默认方式吧

当然如果不嫌麻烦,假设我们将--mixed设置为工作区的指针跟着HEAD跑,暂存区的不变,那么我们必然要多走一步,也就是将暂存区的代码git restore --stage 1.txt回退到工作区,再进行操作,想想都觉得麻烦~

总结

模式 git reset --soft git reset --mixed (默认) git reset --hard
HEAD 指针 移动 移动 移动
暂存区 (Index) 不动 重置到 HEAD 重置到 HEAD
工作区 (Working Dir) 不动 不动 重置到 HEAD

以上只是我这个刚开始学习计算机知识小白的一些拙见,作为学习记录,或许会有人在刚学git的时候有些类似的疑惑,欢迎大家批评!

相关推荐
扛麻袋的少年4 小时前
git reset 和 git reflog 解决代码分支提交错误
git
放学有种别跑、5 小时前
GIT使用指南
大数据·linux·git·elasticsearch
雨雨雨雨雨别下啦5 小时前
【从0开始学前端】 Git版本控制系统
前端·git
happyCoder7 小时前
VS Code Git 神器:内置功能与GitLens插件使用技巧
git·github
小番茄夫斯基7 小时前
深入解析 git merge 和 git rebase 的区别
git
不会写程序的未来程序员7 小时前
详细的 Git 操作分步指南
大数据·git·elasticsearch
芒鸽7 小时前
高效团队协作的基石:Git流程规范详解
git
云计算练习生11 小时前
linux shell编程实战 10 Git工具详解与运维场景实战
linux·运维·git
MUTA️1 天前
git传输超过100MB的文件
git