来聊聊 checkout 吧, 以及碰到紧急打包这种事儿.
checkout 的本质
在前面的 branch
的部分,我说到 checkout
可以用来切换 branch
:
|
|
不过实质上,checkout
并不止可以切换 branch
。checkout
本质上的功能其实是:签出( checkout
)指定的 commit
。
git checkout branch名
的本质,其实是把 HEAD
指向指定的 branch
,然后签出这个 branch
所对应的 commit
的工作目录。所以同样的,checkout
的目标也可以不是 branch
,而直接指定某个 commit
:
|
|
|
|
|
|
|
|
这些都是可以的。
另外,如果你留心的话可能会发现,在 git status
的提示语中,Git 会告诉你可以用 checkout -- 文件名
的格式,通过「签出」的方式来撤销指定文件的修改:
checkout 和 reset 的不同
checkout
和 reset
都可以切换 HEAD
的位置,它们除了有许多细节的差异外,最大的区别在于:reset
在移动 HEAD
时会带着它所指向的 branch
一起移动,而 checkout
不会。当你用 checkout
指向其他地方的时候,HEAD
和 它所指向的 branch
就自动脱离了。
事实上,checkout
有一个专门用来只让 HEAD
和 branch
脱离而不移动 HEAD
的用法:
|
|
执行这行代码,Git 就会把 HEAD
和 branch
脱离,直接指向当前 commit
:
小结
checkout
的本质是签出指定的 commit
,所以你不止可以切换 branch
,也可以直接指定 commit
作为参数,来把 HEAD
移动到指定的 commit
。
紧急情况:「立即给我打个包,现在马上!」
前面在讲 branch
的时候讲到,利用 branch
可以实现一人多任务的需求,从而可以轻松应对「嘿,这个先别做了,给你个新活」的情况。但有时,尤其是在互联网公司,你可能会遇到比这更紧急的情况:你正对着电脑发呆,忽然见到一个同事屁股着着火就跑来找你了:「快快快,立即给我打个包,现在马上,拜托拜托!」
这种情况和「这个 branch
先放放吧」不同,你没时间、也没必要当场慌慌张张把文件的所有改动做个临时的 commit
然后去救同事的火,救完火再重新把 commit
撤销回来。这时候你只要先把所有文件一股脑扔在一边就可以去给同事打包了,打完包再把刚才扔到一边的文件重新取过来就好。
这一「扔」一「取」,用的是 Git 的 stash
指令。
stash:临时存放工作目录的改动
“stash” 这个词,和它意思比较接近的中文翻译是「藏匿」,是「把东西放在一个秘密的地方以备未来使用」的意思。在 Git 中,stash
指令可以帮你把工作目录的内容全部放在你本地的一个独立的地方,它不会被提交,也不会被删除,你把东西放起来之后就可以去做你的临时工作了,做完以后再来取走,就可以继续之前手头的事了。
具体说来,stash
的用法很简单。当你手头有一件临时工作要做,需要把工作目录暂时清理干净,那么你可以:
|
|
就这么简单,你的工作目录的改动就被清空了,所有改动都被存了起来。
然后你就可以从你当前的工作分支切到 master
去给你的同事打包了……
打完包,切回你的分支,然后:
|
|
branch 删过了才想起来有用?
branch
用完就删是好习惯,但有的时候,不小心手残删了一个还有用的 branch
,或者把一个 branch
删掉了才想起来它还有用,怎么办?
reflog :引用的 log
reflog
是 “reference log” 的缩写,使用它可以查看 Git 仓库中的引用的移动记录。如果不指定引用,它会显示 HEAD
的移动记录。假如你误删了 branch1
这个 branch
,那么你可以查看一下 HEAD
的移动历史:
|
|
从图中可以看出,HEAD
的最后一次移动行为是「从 branch1
移动到 master
」。而在这之后,branch1
就被删除了。所以它之前的那个 commit
就是 branch1
被删除之前的位置了,也就是第二行的 c08de9a
。
所以现在就可以切换回 c08de9a
,然后重新创建 branch1
:
|
|
这样,你刚删除的 branch1
就找回来了。
注意:不再被引用直接或间接指向的
commits
会在一定时间后被 Git 回收,所以使用reflog
来找回删除的branch
的操作一定要及时,不然有可能会由于commit
被回收而再也找不回来。
查看其他引用的 reflog
reflog
默认查看 HEAD
的移动历史,除此之外,也可以手动加上名称来查看其他引用的移动历史,例如某个 branch
:
|
|