当我们对一个地方git init
之后会生成.git
文件,此文件记录当前仓库版本迭代信息,表示当前文件夹下就是一个 git 仓库,当前仓库的改动会被 git 所识别和记录
改动未 add:当我们修改了一个文件还未 add 的时候,我们git status
发现改文件是红色的,表示此文件被改动还没有 add,当前修改项目的区域我们称之为工作区,工作区这个概念很重要,就是仓库中我们直接修改代码的地方,git 会显示需要被 added
add 未 commit:当我们成功 add 之后,再用git status
查看,会发现文件变成了绿色,表示已经成功 add 了,但是未 commit,这个绿色的文件在哪呢?在 git 的 stage 暂存区中,这个 stage 暂存区表示即将 commit 的一个缓冲区域,可以 add 不同文件到 stage 暂存区,以后可以一次 commit 来更迭版本
已 commit:当我们成功 commit 文件之后,git status
没有文件显示(IDE 中表现为文件白色),表示 commit 成功,commit 就表示仓库整个版本的更新迭代,就是修改了某一个文件的一个句号,最后 commit 提交成功,都会迭代整个版本,版本迭代在 git 数据结构中表现为版本库的指针往后移动一位,以后要讲解的回退版本操作就是通过指针移动到之前版本来理解
仅仅是在工作区把代码改动了一下,但是还没有来得及 add 这个文件,我们想还原最开始的样子该怎么办呢
git checkout -- README.md
这个文件我改动了然后 add 了,但是还没有 commit,之后我又改动了这个文件,可是这时候我想要将其还原成 stage 暂存区中的内容
git checkout -- README.md
这个文件我改动了,然后 add 了,未 commit,这个时候又改动了这个文件,但是此时我想将其 add 操作撤销,也就是删掉 stage 中的内容
如果撤销某个文件的 add:
# 只撤销该文件的 add
git reset HEAD README.md
如果撤销 stage 暂存区所有的 add
# 撤销 stage 暂存区所有的 add
git reset HEAD
这个相当于场景三和场景一的结合
# 场景三
git reset HEAD README.md
# 场景一
git checkout -- README.md
由于 commit 是整体项目仓库的版本迭代,即使是你只提交了一个文件,所以回退一般针对于整体而言,而非单个文件
项目中已经 add 和 commit 了,版本已经更新了,这时候我又写了一部分代码在工作区,突然我发现这个版本有问题想要将当前版本还原成上一次 commit 的版本,但同时保留当前工作区的所有新代码,但暂存区会被清空
reset 不带有模式默认就是 --mixed,表示保留工作区
git reset HEAD^
或者我们可以这样写git reset --mixed HEAD^
也是一样的效果
由于 commit 是整体仓库的版本迭代,即使是你只提交了一个文件,所以回退一般针对于整体而言,所以说对于单个文件的版本回退是不成功的,但是 git 有其他办法来实现这个功能
假如我 commit 了多个文件作为一个版本的话,我现在只想回退其中一个文件的版本该怎么办呢?实际上我们回退它并不会真正的回退整个仓库的版本,当我们 reset 回退之后,我们可以git log
查看发现版本依旧是当前版本,只不过它会将该文件上一个版本的内容存放在 stage 暂存区内而已
# 回退某个文件版本(其实本质上是无法回退一个文件的版本,因为版本是针对于整个仓库而言。该文件当前依旧是当前版本,该操作只不过是把该文件上一个版本的内容存进了现在的 stage 暂存区内罢了,同时工作区的代码保持不动)
git reset HEAD^ README.md
# 提交暂存区的代码,让文件变成上一个版本的模样,最终在结果上表现为该文件版本回退了,但是我们查看该文件的 log 信息,发现它的版本实际上是不减反增的
git commit -m "commit file"
这两行执行下来最终结果就表现为这个文件还原成了上一个版本的模样,实际上 log 并没有显示版本回退,反而显示了新增了一个版本。工作区的代码保持最新
我们实际在执行的时候会发现我们无法执行git reset --hard HEAD^ README.md
这个命令,显示 git 错误信息无法执行带有 path 的此命令,再一次说明回退只针对于整个项目仓库的版本而言,对于单个文件本质上无法回退版本!
整个场景可以与前面的前面的场景进行比较,我们发现都是要求还原成上一个版本,但是这个要求工作区的修改全部不保存在工作区中,也就是工作区也还原成上一个版本,这也是--mixed
(默认可以不加)与--hard
的区别所在,mixed 表示工作区的一切变动得到保留,hard 表示回退的很彻底,工作区和暂存区都被回退了,我们建议使用 mixed 默认方式,这样更保险!
git reset --hard HEAD^
假如我们 add commit 二连操作完了,之后我又在工作区改了新代码,这时候我发现这个项目错了好几个版本我要将其还原成某次版本,同时需要保证我工作区代码是最新的
git reset [commit 版本号]
看到上面这么多种场景是不是觉得好麻烦,而且很难去记忆?实际上当我们理解了这些命令之后,就很容易记住了!下面我讲解一下理解的方式
当我们想要把工作区的内容还原成最近一版工作区我们可以使用 checkout 命令
git checkout -- [文件路径]
(注:一旦这个文件被 add 就表示工作区已经更新了一次,还原工作区只能还原成最新的那一版)
当我们想要对整个仓库进行版本回退我们可以使用 reset 命令
git reset [commit 版本号]
(注:强烈建议不用加 --hard,若还原成上一个版本,版本号用 HEAD^ 即可)
当我们想要对仓库某一个文件进行版本回退我们可以用 reset 操作单独文件,来将该文件的某次版本保存进当前 stage 暂存区中
git reset [commit 版本号] [文件名]
git commit -m "该文件变成以前的版本"
(注:本质上并不会回退,该文件依旧是当前版本,只不过某次版本存放在了 stage 暂存区中,我们下一步再 commit 即可让该文件变成以前的版本)
当我们想要对仓库某个文件 add 提交进行撤销,我们也可以用 reset [当前版本号] 的操作
git reset HEAD [文件名]
(注:不得不注意的是git reset [版本号]
操作单独文件是比较特殊的,因为原则上单个文件不存在版本回退操作,但限于需求,若是想将该文件回退到以往的版本,此操作的结果是工作区保持不变,当前版本不变,当前 stage 暂存区变成目标版本;若版本号为当前版本 HEAD,此操作的结果是工作区保持不变,当前版本不变,当前 stage 暂存区清空,其实本质就是体现在 stage 区域是之前的版本还是被清空罢了)