習(xí)(2)撤銷與分支操作全指南)
keyipatience:個人主頁作者簡介C/C后端開發(fā)學(xué)習(xí)者專欄傳送門《c》《linux》《c高階數(shù)據(jù)結(jié)構(gòu)》《c數(shù)據(jù)結(jié)構(gòu)與算法》《前端學(xué)習(xí)》??patience is key in lifeGit 撤銷修改情況 1只改了文件沒有 add修改只在工作區(qū)文件改壞了還沒 add想撤銷這一輪改動恢復(fù)到最近一次 add /commit 的樣子 命令git checkout -- ReadMe # 新版git等價推薦寫法 git restore ReadMe重點--不能省 如果寫成git checkout ReadMegit 會理解成【切換到名叫 ReadMe 的分支】含義完全變了。作用 直接把工作區(qū)的改動抹掉文件變回暫存區(qū) / 版本庫里保存的樣子剛才新增的內(nèi)容直接消失。風(fēng)險這個操作直接丟掉你工作區(qū)的修改無法找回謹慎使用情況 2已經(jīng) add但是還沒有 commit修改在暫存區(qū)你已經(jīng)git add ReadMe修改進到暫存區(qū)了現(xiàn)在后悔想撤出來 分兩步走先把修改從暫存區(qū)撤回到工作區(qū)git reset HEAD ReadMe # 等價 git reset --mixed HEAD ReadMe--mixed是默認參數(shù)可以省略 //底層理解HEAD代表當(dāng)前最新的 commit 版本庫快照因為還有沒有commit所以回退到當(dāng)前最新的commit版本就是把 暫存區(qū)stage清空執(zhí)行后效果暫存區(qū)清空文件的內(nèi)容不變改動重新回到工作區(qū)接下來二選一改一改重新git add不想要了用git checkout -- ReadMe/git restore ReadMe刪掉工作區(qū)改動情況 3已經(jīng) add commit修改提交進版本庫了已經(jīng) commit生成一條版本記錄現(xiàn)在想要撤銷這次提交重要前提這個 commit 還沒有 push 推送到遠程倉庫如果已經(jīng) push 到遠端不能隨便用--hard回退后面學(xué)遠程會講命令git reset --hard HEAD^HEAD^當(dāng)前版本的上一個 commit--hard同時改動三處版本庫指針、暫存區(qū)、工作區(qū)執(zhí)行完HEAD 指針挪到上一個版本暫存區(qū)清空工作區(qū)直接變成上個版本的樣子本次 commit 寫的內(nèi)容本地消失。一張匯總表場景狀態(tài)目標(biāo)命令1修改僅在工作區(qū)未 add丟掉工作區(qū)修改git checkout -- 文件名/git restore 文件名2已經(jīng) add未 commit取消暫存退回工作區(qū)git reset HEAD 文件名2 續(xù)取消暫存后想徹底刪掉修改丟掉工作區(qū)修改git checkout -- 文件名3add commit未 push 遠程回退到上一個版本刪掉本次提交git reset --hard HEAD^文件名和HEAD系列分清楚寫HEAD撤回提交管整條記錄寫文件名只取消 add只管這一個文件不碰提交想撤回【整個 commit 提交】后面寫HEAD、HEAD^、一串 commit 哈希號作用把這一次提交給撤掉改提交歷史。這里不帶文件名管的是整條提交記錄。git reset --soft HEAD^ git reset --hard HEAD^后面寫文件名git reset [HEAD] file2.txt//[HEAD可以省略]剛才git add file2.txt加到暫存區(qū)了現(xiàn)在把它拿出來。不會撤銷 commit不會改動提交歷史Git 刪除文件在 git 眼里刪除文件 也是一種修改需要 add /commit 記錄這個刪除動作直接用 linux 的rm file5只刪工作區(qū)rm file5效果本地磁盤工作區(qū)file5 刪掉了版本庫、暫存區(qū)里還保留這個文件git status提示deleted: file5紅色Changes not staged for commit問題git 只是發(fā)現(xiàn)你在本地刪了但是還沒有把 “刪除這件事” 登記到版本庫里。 現(xiàn)在分兩條路刪錯了 確實要刪掉情況 A刪錯了想要恢復(fù)回來剛才只是rm file5還沒執(zhí)行g(shù)it rm、沒 commit 用之前學(xué)過的撤銷工作區(qū)修改命令git checkout -- file5 # 新版等價git restore file5從版本庫把 file5 拿回來恢復(fù)到工作區(qū)ls 又能看到 file5 了。情況 B確實想要把文件從版本庫刪掉git rm file5它一次性做兩件事刪除工作區(qū)的 file5如果還在的話把【刪除 file5】這個動作加到暫存區(qū)git rm≠ linux 的 rm linux rm只動本地磁盤git 不知情git rm同時操作工作區(qū) 暫存區(qū)告訴 git我要刪除這個文件然后必須 commit這個刪除才正式寫入版本庫git commit -m deleted file5文件已經(jīng)加到暫存想只從暫存區(qū)刪掉、本地保留不是真刪文件git rm --cached file5本地磁盤 file5還在只把它從暫存區(qū) / 版本追蹤里移除一般用來取消跟蹤比如誤 add 了大文件和reset效果一樣Git 分支基礎(chǔ)分支 平行宇宙主線master是一條時間線從某個提交點分出新分支就開出一條獨立時間線分支之間互不干擾可以在不同分支寫不同代碼后面還能合并。例子master 主線正常開發(fā)開新分支寫新功能寫完再合并回主線。master和HEADmaster指向最新提交HEAD指向當(dāng)前所在分支只有一個master是主分支指針指向這個分支上最新的一次提交。每commit一次master就自動向后移動一步。HEAD是當(dāng)前所在分支的標(biāo)記先指向master再由master指向最新提交。HEAD → master → 最新提交Git 創(chuàng)建分支git branch # 查看本地所有分支帶 * 的是當(dāng)前分支 git branch dev # 新建 dev 分支只創(chuàng)建不切換過去執(zhí)行完git branch dev之后分支列表dev、* master→*代表 HEAD 當(dāng)前在 master去.git/refs/heads/目錄下看會多出一個dev文件ls .git/refs/heads/ cat .git/refs/heads/*master 和 dev 兩個文件里存的 commit hash 值一模一樣說明剛創(chuàng)建出來的 dev 和 master 指向同一個提交節(jié)點git branch dev只是新增一個指針不會復(fù)制文件、不會新建提交非常輕量這是 Git 分支高效的核心原因。Git 切換分支 分支獨立提交切換分支命令git checkout dev # 等價新版推薦寫法git switch dev執(zhí)行后輸出Switched to branch dev查看分支git branch*跑到 dev 前面代表當(dāng)前分支是 dev底層驗證 HEADcat .git/HEAD # 輸出 ref: refs/heads/dev原理HEAD 指針移動指向 dev 分支原理圖變化HEAD → devmaster 指針還停留在原來那個提交上不動。在 dev 分支做修改并提交vim ReadMe # 修改文件新增一行 write aaa for new branch git add . git commit -m modify ReadMe提交成功提示[dev 274bdce] modify ReadMe這個提交只會讓 dev 分支指針向前移動一步master 指針原地不動不會跟著更新底層查看兩個分支指向的 commit 哈希cat .git/refs/heads/dev # 拿到新的 commit id剛提交的 cat .git/refs/heads/master # 還是原來舊的 commit id核心兩個分支指針現(xiàn)在指向不同提交節(jié)點兩條分支歷史開始分叉切回 master 分支現(xiàn)象新增內(nèi)容消失git checkout master注意如果dev 改了文件不 add、不 commit切回 master新加內(nèi)容還在因為這個改動還沒有存入 Git 的版本庫不在任何分支、不在任何提交里它只躺在你的本地工作目錄。 Git 在切換分支的時候先檢查工作區(qū)有沒有未暫存、未提交的修改如果切換前后的兩個分支這個文件沒有版本差異Git 就不會覆蓋你的改動直接把這份修改保留、帶到目標(biāo)分支查看 ReadMe剛才新增那一行不見了 再切回去 devgit checkout devReadMe 新增內(nèi)容又回來了為什么會這樣這次提交是在 dev 分支上做的master 分支根本沒有包含這次提交切換到 master 時Git 將工作區(qū)恢復(fù)成 master 指向的那個舊提交對應(yīng)的文件版本切換回 devGit 又把工作區(qū)換回 dev 最新提交的文件快照。Git 合并分支Fast-forward 快進合并承接前面流程dev 分支比 master 多了一次提交現(xiàn)在要把 dev 的改動合并進 master。整套命令流程git branch # 查看當(dāng)前分支現(xiàn)在在 dev git checkout master # 先切到 master合并是【把別的分支合并到當(dāng)前分支】 git merge dev # 將 dev 合并到 master輸出關(guān)鍵信息Updating 16623e1..3740dce Fast-forward ReadMe | 1 1 file changed, 1 insertion()查看 ReadMemaster 里面也出現(xiàn)了 dev 新增的那一行內(nèi)容。重點規(guī)則git merge [分支名]的含義把指定分支合并到【你現(xiàn)在所在的分支】所以合并前一定要先切到目標(biāo)分支這里是 master。Fast-forward快進模式是什么原理圖變化 合并前master 停在舊提交點dev 在 master 的正前方順著一條線往前走了一次提交快進合并的時候Git不產(chǎn)生新的提交記錄只是直接移動 master 指針?biāo)晕覀儾缓脜^(qū)分到底是merge讓指針移動一步還是在master分支上commit一次讓指針移動讓 master 指向和 dev 同一個提交節(jié)點。所以快進合并沒有生成新提交merge 命令執(zhí)行完就結(jié)束了不用再敲git commit。Git 刪除分支命令git branch -d devd--delete安全刪除分支。兩個硬性規(guī)則1.不能刪除當(dāng)前所在的分支* 例子現(xiàn)在在 dev* dev執(zhí)行g(shù)it branch -d deverror: Cannot delete branch dev checked out at xxx2.正確做法先切到別的分支一般切 master/main再刪git checkout master git branch -d dev-d安全刪除的底層限制git branch -d是安全模式Git 會檢查這個分支的所有提交是不是已經(jīng)被別的分支合并、能訪問到了。像如果dev已經(jīng)合并進 master→ 可以-d刪除如果 dev 獨有的提交還沒有合并進主分支直接-d會拒絕刪除防止你丟提交大寫-D強制刪除危險git branch -D dev-D --delete --force不管分支有沒有合并、有沒有獨有的提交直接刪掉分支指針。Git 鼓勵你使用分支完成某個任務(wù)合并后再刪掉分支這和直接在 master 分支上工作效果是一樣的但過程更安全。即開發(fā)新功能、改 bug新建 dev 分支干活測試沒問題合并到主分支 master合并完成dev 使命結(jié)束刪除它 好處master 全程保持干凈穩(wěn)定開發(fā)過程中的錯誤、半成品不會污染主分支