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