git checkout命令的實質就是修改HEAD本身的指向,該命令不會影響分支"游標"(如master)
HEAD的重置即檢出
HEAD可以理解為"頭指針",是當前工作區(qū)的基礎版本,當執(zhí)行提交時,HEAD指向的提交將作為新提交的父提交。
git branch -v
結果
- *master b2a5a95 does master follow this new commit
然后執(zhí)行如下命令
git checkout b2a5a95 ^
就會處于"分離頭指針"狀態(tài)。該狀態(tài)是指HEAD頭指針指向的是一個具體的提交ID,而不是一個引用(分支)
然后創(chuàng)建一個文件touch detached-commit.txt,加到暫存區(qū)git add detached-commit.txt,再然后git commit -m "commit in detached HEAD mode",此時頭指針指向了新的提交,然后再git checkout master回到master分支,HEAD重新指向了master分支,而不是出于"分離頭模式",切換之后,之前新建了本地文件detached-commit.txt不見了,剛剛提交的日志也不見了。但是使用git show [剛剛提交的ID]命令能在版本庫中看到這個提交,但由于這個提交沒有被任何分支跟蹤到,因此并不能保證這個提交會永久的存在。實際上當reflog中含有該提交的日志過期后,這個提交隨時會從版本庫中徹底清除掉
挽救分離頭指針
在"分離頭指針"模式下進行的提交除了使用提交的ID來訪問之外,不能通過master分支或者其他分支訪問到,如果這個提交時master分支所需要的,那么該如何處理呢?如果使用git reset命令把master分支重置到該測試提交的分支上,那么會丟掉master指向的當前的提交。使用git merge合并操作可以兩者兼顧。
深入了解git checkout命令
- 用法一
git checkout [-q] [<commit>] [--] <paths> - 用法二
git checkout [<branch>] - 用法三
git checkout [-m] [[-b|--orphan] <new_branch>] [<start_point>]
第一種用法的<commit>是可選項,如果省略則相當于從暫存區(qū)檢出,這和git reset不一樣,git reset默認的是HEAD,而git checkout默認的是暫存區(qū),因此重置一般用于重置暫存區(qū)(除非使用了--hard參數(shù),否則不會重置工作區(qū)),而檢出命令主要是覆蓋工作區(qū)(如果<commit>參數(shù)不省略,也會替換暫存區(qū)中相關的文件)
第一種用法不會改變HEAD的頭指針,主要用于指定版本的文件覆蓋工作區(qū)中對應的文件。如果省略了<commit>,則會用暫存區(qū)的文件覆蓋工作區(qū)的文件,否則用指定提交中的文件覆蓋暫存區(qū)和工作區(qū)中對應的文件
第二種用法最主要的作用是切換分支。如果省略<branch>則相當于對工作區(qū)進行狀態(tài)檢查
第三種用法主要是創(chuàng)建和切換分支(<new_branch>),新的分支從<start_point>指定的提交開始創(chuàng)建。
下圖展示了檢出命令和版本庫之間的關系
檢出命令和版本庫
示例用法: -
git checkout branch檢出到branch分支,會執(zhí)行1,2,3步驟。更新HEAD指向以指向branch分支以及用branch指向的樹更新暫存區(qū)和工作區(qū) -
git checkout匯總顯示工作區(qū),暫存區(qū)與HEAD的差異 -
git checkout HEAD效果同上
-git checkout -- filename用暫存區(qū)中filename文件來覆蓋工作區(qū)的filename文件。相當于取消自上次執(zhí)行git add filename命令以來工作區(qū)的本地修改 -
git checkout branch -- filename維護HEAD的指向不變,用branch所指向的提交的filename文件替換掉工作區(qū)和暫存區(qū)中相應的文件 -
git checkout -- .或者git checkout .這條命令很危險,會取消所有本地的修改(相當于暫存區(qū))。相當于用暫存區(qū)的所有文件直接覆蓋本地文件。不給用戶任何確認的機會
