【Git常用】之回滚

一、基础

回滚是一个版本管理系统最重要的功能之一。
由于Git的设计,导致Git的回滚在新手面前十分难理解。
本文从结果出发,总结了对于使用者来说最常用的操作,在不了解Git的深层原理时,可以快速上手使用。

二、说明

实验环境:Windows 10,Git版本2.21.0
实验环境
为了方便演示,编者自己只做了一个简单的Git项目,项目中只有一个README.md文件。
git项目
第一次提交内容为v1,第二次为v2,第三次为v3,现在的提交历史及仓库状况如下图所示。
在这里插入图片描述
一图胜千言。
提交历史图示
我们把仓库(Repository)、暂存区(Index)和工作目录(Working Directory) 同时画进图中,方便后续理解。
仓库、暂存区和工作目录
大概就是这个样子:我们在master分支上提交了三次,所以仓库中有三次记录,暂存区和最新的提交一样,工作目录我们没有修改什么,和仓库一样。

深入理解这张图片需要理解如下内容:

  1. 分支的本质是一系列提交的链接,分支(图中master)一般情况下指向最新的提交(链末尾),我们通过引用指向提交的指针来操作分支。
  2. HEAD也是一个指向提交的指针,表示当前所在的分支,一般情况下指向当前分支。
  3. Git存储文档的方式见【Git常用】之深入理解Git存储文档的方式

三、常用操作总结

3.1 回顾add与commit

将工作目录中的README修改为v4,本次提交想输入的提交信息为“forth commit”,现在如下:
在这里插入图片描述
运行$ git add README.md,相信你一定可以理解下图。
git add的效果
运行$ git commit -m 'forth commit',就变成了如下的样子。
git commit的效果

3.2 取消add

这里说“取消add”,可以理解为(git的做法)将Repository的最新提交覆盖到Index中。

按照git bash中的提示,使用命令$ git reset HEAD <file>可以达到此目的。

我们回到3.1中运行$ git commit,提交v4之前的这一步。
git add的效果
运行$ git reset HEAD README.md,运行结果如图
在这里插入图片描述
想要理解这个命令做了什么,请看3.4。

3.3 取消修改

很简单,就是我修改的都不想要了,是整个工作目录回退到一个干净的状态,和仓库的代码一致。

我们回到3.1中$ git add,添加v4之前这一步。
在这里插入图片描述
运行$ git checkout -- README.md,运行结果如图
在这里插入图片描述

3.4 取消一次提交

以上展示的都没有操作git提交的历史,都是在完好的提交历史基础上进行三个区域的操作。

假设v4版本的提交不想要了,又如何操作呢?

让我们回到这一步。
在这里插入图片描述
经历过3.2,我们思考,是不是把v3提交从Repository中复制出来,复制给Index和Working Directory不就搞定了?

Git确实也是这么做的。

使用$ git reset --hard HEAD^,执行结果:
在这里插入图片描述

解析:

  1. 第一步,将HEAD和master向目标提交移动,HEAD^表示HEAD所在的提交的父提交
  2. 第二步,将目标提交复制到Index。
  3. 第三部,将Index复制到Working Directory。-- hard参数在这里起了作用,表示需要修改Working Directory

有意思的是,我们可以通过指定参数,让git reset命令并不都执行这三步。

$ git reset --soft HEAD^只会执行第一步,这样的结果看起来如下。
在这里插入图片描述
$ git reset --mixed HEAD^只会执行到第二步,这样的结果看起来如下。
在这里插入图片描述
等等,这个命令的作用,和之前3.2提到的$ git reset HEAD <file>有异曲同工之妙。

是的,没错,他们是一个命令。原因在于:

  1. $ git reset默认携带--mixed参数
  2. $ git reset HEAD <file>指定的提交是HEAD,即master最新的提交,所以在3.2的条件下,git将v3的内容复制出来给Index

这就是git的做法。

还有一个区别是3.2的命令指定了一个文件,这个很好理解,就是该文件单独处理。

总结一下,关于$ git reset

  1. 第一步,移动HEAD和分支指针到目标提交git reset --soft [branch]在此停止。
  2. 第二步,将目标提交复制到Index。git reset <--mixed> [branch]在此停止。
  3. 第三部,将Index复制到Working Directory。git reset --hard [branch]在此停止。

想要修改某些文件,则可以使用git reset <--mixed> [file]--soft--hard都不可以加文件

但是这会跳过第一步

我们来尝试一下,仓库如下图所示状态。
在这里插入图片描述
执行$ git reset --mixed HEAD^ README.md,结果如下。
在这里插入图片描述
可以看到,HEAD和master没有移动,但是Index变成了v3的内容,即执行了第二步,将HEAD的父提交v3复制到Index,并停止。

3.5 checkout

现在来理解checkout。

$ git checkout [branch]$ git reset --hard [branch]一样,都可以操作三个区域。不同的是:

  1. checkout只移动HEAD,不改变master(举例来说)。
  2. checkout不会像--hard一样强制修改Working Directory,他会检查甚至自动合并。

运行$ git checkout 2b0d18b结果如图。
在这里插入图片描述
这时git处于“detached HEAD”状态。
在这里插入图片描述

如果使用$ git checkout -- <file>,则一样会跳过“第一步“和”第二步“,使用HEAD中文件覆盖工作区域。

reset命令并没有删除提交,v4还在那里,我们可以使用SHA-1值去索引到它。

四、总结

三个区域的文件迁移关系如下图所示。

在这里插入图片描述

注:

  1. 这里的迁移关系只是示意图,并没有表示出命令完整的作用。reset有三个步骤,请理解以后再来看此图。
  2. 关于$ git checkout -- <file>的作用,编者亲自做了实验,发现并没有修改Index区,和《Git Pro》中的说法不一致,欢迎大家留言讨论。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值