匿名分支
(前提:创建一个新的文件夹(MyProject3),然后初始化 git,然后新建三个txt文件,然后加到仓中)
直接实用git checkout命令后发现:
当前的 HEAD 指针处于分离状态,你可以环顾四周,做一些实验性修改并提交它们,并且你可以在这个状态中丢弃任何你所做的提交,而不影响任何分支,做法是执行 checkout 命令切换回别的分支。
如果你希望创建一个新分支,并保持你所做创建的提交,你可以(现在或稍后)通过使用带有 -b 选项的 checkout 命令实现。例如:
git checkout -b <new-branch-name>
HEAD 指针当前指向 be7ba0...2.txt
发现3.txt不见了,然后再建一个4.txt
执行 git log --decorate --all --graph --oneline 命令:
以看到有两个分支,但 HEAD 所在的分支并没有名字(匿名分支),那现在我们把 HEAD 切回 master 分支:
警告:你残留一个没有连接任何分支的提交:
178d909 4.txt
如果你想通过创建一个分支来连接它,这将是一个好时机,请执行:
git branch <new-branch-name> b46c2f3
已经切换到 'master' 分支
现在再来查看提交日志,可以看到匿名分支已经荡然无存:
再论 checkout
从历史快照(或者暂存区域)中拷贝文件到工作目录
当给定某个文件名时,Git 会从指定的提交中拷贝文件到暂存区域和工作目录。比如执行 git checkout HEAD~ README.md 命令会将上一个快照中的 README.md 文件复制到工作目录和暂存区域中:
如果命令中没有指定具体的快照 ID,则将从暂存区域恢复指定文件到工作目录(git checkout README.md)
注意:写成 git checkout -- README.md 的形式,约定两个横杆(--)后边跟的是文件名。(确保后面的文件名和分支名不重复)
切换分支
首先我们知道 Git 的分支其实就是添加一个指向快照的指针,其次我们还知道切换分支除了修改 HEAD 指针的指向,还会改变暂存区域和工作目录的内容。
所以执行 git checkout 373c0 命令,Git 主要就是做了下边这两件事
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 master 命令将其切回。
现在执行 git reset --hard feature 命令:
reset 命令将 HEAD 指向的分支以及 HEAD 本身都切到了 feature 分支里,换句话说,原来的快照已经被消失了
(额外:只需要在 merge 的时候使用 --no-ff 选项即可告诉 Git 不要使用 Fast-forward 方式合并分支。保留分支信息git merge --on--ff featurem 这样就算删掉了“feature”分支,我们仍然可以很容易看出有个分支曾经存在过)