在前面的branch的部分介绍过checkout可以用来切换branch:
git checkout branch2不过实质上,checkout并不止可以切换branch。checkout本质功能其实是:签出(checkout)指定的commit。
git checkout branch名的本质,其实是让HEAD指向对应的branch,然后签出这个branch对应commit的工作目录。同样的,checkout的目标也可以不是branch,而是直接指向某个commit:
git checkout HEAD^^git checkout master~5git checkout 78a4bcgit checkout 78a4bc^这些都是可以的。
另外,如果你留心的话可能会发现,在git status的提示信息中,Git 会告诉你可以用checkout -- 文件名的格式,通过「签出」的方式来撤销(丢弃)指定文件的修改:
切换分支
- 切换到已有分支:
git checkout <分支名>就能跳到目标分支,工作区文件会自动更新成该分支的内容 。 - 创建并切换新分支:
git checkout -b <新分支名>一键创建新分支并切过去,相当于先建分支再切换两步合为一步 。 - 切换到远程分支:
git checkout -t origin/<分支名>能从远程仓库检出分支并在本地创建跟踪分支 。 - 进入分离头指针状态:
git checkout <commit-SHA>会进入detached HEAD状态,适合查看历史代码或调试旧版本,但在此状态下提交的内容不会关联到任何分支 。
恢复文件版本
- 丢弃未提交的修改:
git checkout --<文件名>把文件恢复到最近一次提交或暂存的状态,本地未提交的改动会永久丢失 。 - 从其他分支恢复文件:
git checkout <分支名> --<文件名>把指定分支上的某个文件复制到当前分支,无需合并整个分支 。 - 恢复已删除文件:如果文件被误删但未提交,用
git checkout HEAD --<文件名>能从最后一次提交中恢复 。 - 交互式恢复部分代码:加上
-p参数如git checkout -p --<文件名>可以逐块选择要恢复的代码,适合只想撤销部分改动的场景 。
需要注意的地方
- 未提交修改会阻止切换:如果工作区有与目标分支冲突的未提交修改,Git 会阻止切换,建议先用
git stash暂存或提交后再切换 。 - 强制切换会丢数据:使用
-f参数如git checkout -f <分支名>会强制切换并丢弃所有未提交修改,操作前务必确认 。 - 新命令更清晰:Git 2.23 版本后引入了
git switch专门切换分支、git restore专门恢复文件,语义更明确,但checkout仍被广泛使用 。 - 文件名与分支名冲突:如果有个文件名叫hello.c同时也有个分支叫hello.c,Git 会优先当作分支处理,此时需用
git checkout -- hello.c明确指定是文件 。
checkout 和 reset 的不同
checkout和reset都可以切换HEAD的位置,它们除了有许多细节的差异外,最大的区别在于:reset在移动HEAD时会带着它所指向的branch一起移动,而checkout不会。当你用checkout指向其他地方的时候,HEAD和它所指向的branch就自动脱离了。
事实上,checkout有一个专门用来只让HEAD和branch脱离而不移动HEAD的用法:
git checkout --detach执行这行代码,Git 就会把HEAD和branch脱离,直接指向当前commit:
小结
checkout的本质是签出指定的commit,所以你不止可以切换branch,也可以直接指定commit的 SHA-1 作为参数,来把HEAD移动到指定的commit。