这节课我们来重新回顾一下 checkout 命令,然后我们再来讲讲 reset 命令(忘了的可以查看Git实用教程 4.0:回到过去) 和 checkout 命令 的主要区别。
再论 checkout
接下来我们再来谈论一下 checkout 命令吧!
我觉得很多童鞋可能会被这个命令弄迷糊,所以这里还是给大家伙总结一下好。
事实上呢,checkout 命令有两种功能:
- 从历史快照(或者暂存区域)中拷贝文件到工作目录
- 切换分支
功能1:从历史快照(或者暂存区域)中拷贝文件到工作目录
当给定某个文件名时,Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行 git checkout HEAD~ README.md 命令会将上一个快照中的 README.md 文件复制到工作目录和暂存区域中:
如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录(git checkout README.md):
有些朋友可能会问:“上次看你在文件名的前边有加两个横杆(--),这次怎么就没有了呢?”
问得好,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 就会忽略第一步修改 HEAD 指向的操作,这不正跟之前讲 reset 命令的时候一样吗?
checkout 命令和 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 checkout feature 命令:
可以看到只是 HEAD 指针跑到 feature 分支那儿去了。
好,我们执行 git checkout master 命令将其切回。
现在执行 git reset --hard feature 命令:
看到区别了吗?
reset 命令将 HEAD 指向的分支以及 HEAD 本身都切到了 feature 分支里,换句话说,原来的快照已经被消失了(5.txt 那个快照不见了)。
以下内容属于部分人士查看
准备操作:
在上节课结束时,是下面的情况:
step1:创建 feature 分支 并切换到 feature 分支:
step2:新建 4.txt 文件并添加到 git 仓库:
step3:切换回 master 分支:
step4:新建 5.txt 文件并添加到 git 仓库:
over,大功告成,来看这里的操作答案的童鞋自己好好反省啊,前面的文章肯定没有好好看。