git reset 命令原理

git reset 命令原理


本文摘抄自《Pro Git》

git如何管理版本

认识git

git中有HEAD、Index和working Directory下表是他们的用途

名称用途
HEAD上一次提交的快照,下一次提交的父结点
Index预期的s下一次提交的快照,可以理解为暂存区
Working Directory工作目录

  HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交.
  Indox是预期的下一次提交。 也就是指向 Git 的 “暂存区域”,这就是当你运行 git commit 时 Git 看起来的样子。
  working directory 会将.git文件夹中的内容解包为实际的文件以便编辑,

git的工作流程

  git主要是操纵上述三个地方来实现其版本管理的功能的
在这里插入图片描述  下面我们来一步一步实现这个过程:

step1: 创建git

  假设我们进入到一个新目录,其中有一个文件。 我们称其为该文件的 v1 版本,将它标记为蓝色。 现在运行 git init,这会创建一个 Git 仓库,其中的 HEAD 引用指向未创建的分支(master 还不存在)。
在这里插入图片描述  此时,只有工作目录有内容

step2: 向索引中添加内容

  现在我们想要提交这个文件,所以用git add来获取工作目录中的内容,并将其复制到索引中
在这里插入图片描述

step3: 提交当前版本

  运行git commit,它会取得索引中的内容并将它保存为一个永久的快照,然后创建一个指向该快照的提交对象,最后更新 master 来指向本次提交在这里插入图片描述  现在我们来运行一下git status 命令发现没有任何改动,这是因为现在这三个地方的文件是相同的

step4: 对文件做改动

  现在我们想要对文件进行修改然后提交它。 我们将会经历同样的过程;首先在工作目录中修改文件。 我们称其为该文件的 v2 版本,并将它标记为红色。在这里插入图片描述  如果现在运行 git status,我们会看到文件显示在 “Changes not staged for commit,” 下面并被标记为红色,因为该条目在索引与工作目录之间存在不同。

step5: 将新修改加入暂存区

  我们运行 git add 来将它暂存到索引中
在这里插入图片描述
  此时,由于索引和 HEAD 不同,若运行 git status 的话就会看到 “Changes to be committed” 下的该文件变为绿色 ——也就是说,现在预期的下一次提交与上一次提交不同

step6: 提交新修改

  我们运行 git commit 来完成提交在这里插入图片描述  现在我们来运行一下git status 命令发现没有任何改动,这是因为现在这三个地方的文件是相同的

  以上就是git对版本控制的工作流程以及各个流程阶段工作目录,暂存区和本地仓库的状态

git的分支切换和克隆流程

  切换分支或克隆的过程也类似。 当检出一个分支时,它会修改 HEAD 指向新的分支引用,将 索引 填充为该次提交的快照,然后将 索引 的内容复制到 工作目录 中

重置

  知道了git的工作流程,现在我们可以来看一下git是如何重置的.
  假设我们再次修改了 file.txt 文件并第三次提交它。 现在的历史看起来是这样的:在这里插入图片描述

step1: 移动HEAD(–soft)

   reset做的第一件事是移动 HEAD 的指向. (这与checkout改变 HEAD 自身是不同)
   此时本地的状态如下图所示

在这里插入图片描述   该命令等同与git reset --soft HEAD~如图,它本质上是撤销了上一次 git commit 命令。 当你在运行 git commit 时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交。 当你将它 reset 退回 HEAD~(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录
   如果此时你运行git status命令,你会看到如下输出在这里插入图片描述你现在可以直接使用git commit 将其提交

step2: 更新索引(–mixed)

   接下来,reset 会用 HEAD 指向的当前快照的内容来更新索引
在这里插入图片描述   git在上一步的基础上,取消了暂存区的所有东西,于是,我们回滚到了上次commit之后.
   此时运行git status会看到如下输出:在这里插入图片描述   reset 命令默认就是执行git reset --mixed HEAD~ 所以如果你运行git reset commitID,git会为你清空暂存区并将HEAD指针指向commitID的位置.

step3: 更新工作目录(–hard)

   如果你使用–hard选项,那么git会为你更新工作目录
在这里插入图片描述
   必须注意,–hard 标记是 reset 命令唯一的危险用法,它也是 Git 会真正地销毁数据的仅有的几个操作之一。 其他任何形式的 reset 调用都可以轻松撤消,但是 --hard 选项不能,因为它强制覆盖了工作目录中的文件。 在这种特殊情况下,我们的 Git 数据库中的一个提交内还留有该文件的 v3 版本,我们可以通过 reflog 来找回它。但是若该文件还未提交,Git 仍会覆盖它从而导致无法恢复.

总结

   在使用reset命令时,你可以通过指定参数来选择你想要回滚的位置

  1. 移动该分支中HEAD的指向,保留暂存区和工作目录中的数据 (–soft)
  2. 移动该分支中HEAD的指向,只保留工作目录中的数据(–mixed)
  3. 移动该分支中HEAD的指向,清空暂存区和工作目录(–hard)
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值