Git实用教程10.0:checkout 命令 与 reset 命令

本节主要知识点:


reset 命令 和 checkout 命令 的主要区别




再论 checkout


checkout 命令有两种功能:

  • 从历史快照(或者暂存区域)中拷贝文件到工作目录

  • 切换分支

功能1:从历史快照(或者暂存区域)中拷贝文件到工作目录

当给定某个文件名时,Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行 git checkout HEAD~ README.md 命令会将上一个快照中的 README.md 文件复制到工作目录和暂存区域中:
Git实用教程10.0:checkout 命令 与 reset 命令
如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录(git checkout README.md):
Git实用教程10.0:checkout 命令 与 reset 命令
有些朋友可能会问:“上次看你在文件名的前边有加两个横杆(–),这次怎么就没有了呢?”

Git 提醒你写成 git checkout – README.md 的形式,那是为了预防你恰好有一个分支叫做 README.md,那么它就搞不懂你要恢复文件还是切换分支了,所以约定两个横杆(–)后边跟的是文件名

反过来说,如果你确保你没有一个叫做 README.md 的分支,你直接写 git checkout README.md 也是妥妥的没问题啦

功能2:切换分支

那么我们就会发现 Git 的每一个命令虽然有多种使用方法,但是掌握了一定的门道,记住这些用法并不会很困难。

比如在你的印象中,checkout 命令就是用于切换分支,对不对?

那切换分支的操作,Git 是如何实现的呢?

首先我们知道 Git 的分支其实就是添加一个指向快照的指针,其次我们还知道切换分支除了修改 HEAD 指针的指向,还会改变暂存区域和工作目录的内容。

所以执行 git checkout 373c0 命令,Git 主要就是做了下边这两件事(当然事实上 Git 还做了更多):
Git实用教程10.0:checkout 命令 与 reset 命令
回过头来,如果我们只想恢复指定的文件/路径,那么我们只需要指定具体的文件,Git 就会忽略第一步修改 HEAD 指向的操作,这不正跟之前讲 reset 命令的时候一样吗?


checkout 命令和 reset 命令的区别


  • 恢复文件

checkout 命令和 reset 命令都可以用于恢复指定快照的指定文件,并且它们都不会改变 HEAD 指针的指向。

下面开始划重点:

它们的区别reset 命令只将指定文件恢复到暂存区域(–mixed),而 checkout 命令是同时覆盖暂存区域和工作目录

注意:也许你试图使用 git reset --hard HEAD~ README.md 命令让 reset 同时覆盖工作目录,但 Git 会告诉你这是徒劳(此时 reset 不允许使用 --soft 或 --hard 选项)。

这样看来,在恢复文件方面,reset 命令要比 checkout 命令更安全一些

  • 恢复快照

reset 命令是用来“回到过去”的,根据选项的不同,reset 命令将移动 HEAD 指针(–soft) -> 覆盖暂存区域(–mixed,默认)-> 覆盖工作目录(–hard)。

checkout 命令虽说是用于切换分支,但前面你也看到了,它事实上也是通过移动 HEAD 指针和覆盖暂存区域、工作目录来实现的。

那问题来了:它们有什么区别呢?

下面开始划重点

  • 第一个区别是,对于 reset --hard 命令来说,checkout 命令更安全。因为 checkout 命令在切换分支前会先检查一下当前的工作状态,如果不是“clean”的话,Git 不会允许你这样做;而 reset --hard 命令则是直接覆盖所有数据。

  • 另一个区别是如何更新 HEAD 指向,reset 命令会移动 HEAD 所在分支的指向,而 checkout 命令只会移动 HEAD 自身来指向另一个分支。

我们举例说明。

来,大家先把上节课的例子改成下边这样(大家应该知道怎么做吧,不会的就看文末的准备操作吧):
Git实用教程10.0:checkout 命令 与 reset 命令
执行 git checkout feature 命令:
Git实用教程10.0:checkout 命令 与 reset 命令
可以看到只是 HEAD 指针跑到 feature 分*儿去了。

好,我们执行 git checkout master 命令将其切回。
Git实用教程10.0:checkout 命令 与 reset 命令
现在执行 git reset --hard feature 命令:
Git实用教程10.0:checkout 命令 与 reset 命令
reset 命令将 HEAD 指向的分支以及 HEAD 本身都切到了 feature 分支里,换句话说,原来的快照已经被消失了(5.txt 那个快照不见了)。
Git实用教程10.0:checkout 命令 与 reset 命令


以下内容属于部分人士查看(改成上面的例子)

准备操作:

在上节课结束时,是下面的情况:
Git实用教程10.0:checkout 命令 与 reset 命令
step1:创建 feature 分支 并切换到 feature 分支:
Git实用教程10.0:checkout 命令 与 reset 命令
step2:新建 4.txt 文件并添加到 git 仓库:
Git实用教程10.0:checkout 命令 与 reset 命令
step3:切换回 master 分支:
Git实用教程10.0:checkout 命令 与 reset 命令
step4:新建 5.txt 文件并添加到 git 仓库:
Git实用教程10.0:checkout 命令 与 reset 命令
来看这个的同学前面还要在继续哦,没有掌握扎实!