git思维结构及git reset , git revert区别

项目不尽人意,需要进行回滚,遇到了这两位,遂做随笔记录

在回滚基础上,首先我们应该明确的是git 的“三棵树结构”
想直接了解区别请下滑
三棵树分别是:HEAD,Index,Working Directory

1.HEAD
HEAD 是一个指针,它总是指向该分支上的最后一次提交
你可以理解为,你最后一次commit文件的那次,文件是什么样,HEAD就是指的那次的文件状态

2.Index
索引,官方解释是:预期的下一次提交
说人话:你的暂存区
那些你在工作区进行过的任何修改,都可以提交到暂存区里

3.Working Directory
你的工作区,你可以在这里进行任意的代码编写工作

git的工作流程

首先我们进入到一个新的本地文件中进行代码编写,我们把他记做V1
使用命令 git init来进行git 仓库初始化,即这个文件开始进入到git仓库之中
文件就处于工作区之中
git思维结构及git reset , git revert区别
现在我们觉得代码编写的不错,想进行进一步的保存
使用命令 git add 文件名 来进行文件的修改的暂存
此时文件被复制了一份到暂存区之中
git思维结构及git reset , git revert区别
进一步的,我们觉得这次的修改通过,想把他永久性地保存和记录
使用命令 git commit 来进行提交到本地的git仓库里
此时HEAD就会指向本次提交的文件
git思维结构及git reset , git revert区别
这就是文件从修改到提交的整个过程

进一步,我们继续进行文件编码工作,完善功能
因此文件从v1变为了v2
然后我们想保存整个修改,重复上面的步骤
git add 和 git commit
git思维结构及git reset , git revert区别
这里主要看git仓库的变化,你存在本地的v1版本仍然是存在的,并且HEAD又原来指向V1向后移动,指向了你最新提交的V2
这就是HEAD的含义:总是指向你最后一次提交的文件快照

接下来我们进行第三次的修改 文件变为V3且进行暂存和提交
git思维结构及git reset , git revert区别
接下来我们分别看看三个命令是如何进行工作的(本质上来看)

  • git reset
    git reset命令后面有多种参数可以进行选择
    git reset首先都是移动 HEAD 的指向,将HEAD移动到对应的曾经本地的文件快照上,接着进行的动作和输入的参数有关
    当使用的是 reset --soft
    它将仅仅让HEAD停在我们之前的文件上,也就是只改变HEAD树的内容,其他不变
    git思维结构及git reset , git revert区别

它本质上是撤销了上一次 git commit 命令。 当你在运行 git commit 时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交。 当你将它 reset 回 HEAD~(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录。

当使用的是 reset --mixed
它将不仅仅使HEAD变为之前的版本,index区域的内容也会恢复到之前的版本
git思维结构及git reset , git revert区别
它依然会撤销一上次 提交,但还会 取消暂存 所有的东西。 于是,我们回滚到了所有 git add 和 git commit 的命令执行之前。

当使用的是 reset --hard
git思维结构及git reset , git revert区别
你撤销了最后的提交、git add 和 git commit 命令 以及 工作目录中的所有工作。

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

  • git revert
    使用git revert 可以同样实现文件的版本回滚,并且会更加的温和
    推荐当我们已经推送到远程仓库后想回滚,使用该方法

git revert 的本质是,它是一次新的提交
而只是本次提交修改的内容是我们想回退到的那个版本的内容

就像是将那个版本的内容进行git pull 下拉
然后由你来决定哪些地方保留新的哪些保留旧的

比如上面的例子,我们做了V1,V2,V3三个版本进行了提交
但是我们的V2里面是存在代码错误的,这个时候我们想进行回滚到V1版本,对比来分析git reset和git revert

当我们使用git reset来回滚到V1 那么相当于我们V2,V3所做的所有的操作都将被取消,这时往往会遗失一些重要的东西,因为我们在V2,V3编码的时候并不是所有的代码都是无效的需要删除的
以及我们如果在V2,V3创建了其他的分支的话均会消失
就感觉reset是一个非常强硬的方法
他会给你直接还原到你想去的那个版本,完完全全的还原,不多不少

而当我们使用git revert来进行回滚的话,他相当于一次全新的提交
撤销了V2的,并且V3的修改都会进行保留
然后类似git pull的时候
让你来进行冲突代码的处理,你自己决定哪些需要保留哪些删除
非常的温和

git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

补充:使用git reset 和git revert还原版本的流程:
二者都很相似
前置知识点:每次我们进行commit提交的时候,都会记录在git log中,并且每次的commit 都会自动生成一个commitID
1.使用git log来查看日志
你们会看到自己提交的记录以及对应提交的commitID
git思维结构及git reset , git revert区别
按q退出(这个知识点困惑了好多人!)
2.使用git reset或者git revert commitID来进行回滚