戰(zhàn)指南:核心機(jī)制、分支沖突與SSH認(rèn)證排查)
我用了快十年的Git老實(shí)說最開始那幾年我是靠背命令撐過來的。后來踩過幾次大坑——比如在共享分支上直接reset、把SSH密鑰生成到了錯(cuò)誤目錄導(dǎo)致認(rèn)證失敗、合并沖突時(shí)手一抖把同事的代碼整個(gè)刪掉——才慢慢明白Git真正需要的是理解它背后的模型而不是把命令背全。這篇就把我在實(shí)際項(xiàng)目中反復(fù)用到、也反復(fù)踩坑的部分串起來講一遍從Git的安裝配置講起然后是本地倉庫的核心命令鏈路、分支合并與沖突解決、SSH認(rèn)證失敗的完整排查最后是遠(yuǎn)程倉庫拉取、推送和回滾的高頻場景。內(nèi)容盡量貼近日常開發(fā)適合剛接觸Git的同學(xué)也適合用了一段時(shí)間但總被各種報(bào)錯(cuò)卡住的人。1. 安裝與初始化為什么很多人裝好Git的第一周就卡殼1.1 不同系統(tǒng)的安裝方式與版本選擇先說安裝。Windows用戶建議直接去Git官網(wǎng)下載Git for Windows的安裝包一路Next裝完中途會(huì)有幾個(gè)選擇項(xiàng)比如“選擇默認(rèn)編輯器”“調(diào)整PATH環(huán)境變量”之類的第一項(xiàng)建議選Notepad即可PATH選項(xiàng)選“Git from the command line and also from 3rd-party software”其他保持默認(rèn)就好。裝完之后你會(huì)得到一個(gè)Git Bash這是Windows下最順手的Git終端環(huán)境很多教程里直接打開CMD操作遇到一些編碼和命令兼容問題就很麻煩。macOS這邊如果你裝了Xcode Command Line Tools系統(tǒng)會(huì)自帶一個(gè)Git但版本往往偏舊我遇到過太老的Git連新托管平臺的ED25519密鑰都不認(rèn)的情況。推薦用Homebrew裝一份新版本brew install git裝完看下版本。Linux就看發(fā)行版Debian/Ubuntu用sudo apt install gitCentOS/RHEL系列用sudo yum install gitFedora是sudo dnf install git。裝完后統(tǒng)一跑一句git --version確認(rèn)版本號。如果你看到低于2.30的版本建議想辦法升級一下因?yàn)榻鼛啄甑姆种J(rèn)名、git switch、git restore這些好用的命令都依賴新版。提示git switch和git restore是Git 2.23之后才加入的命令。如果你還在用老版本的git checkout完成切分支和恢復(fù)文件我的建議是先升級再用新命令能少踩不少“誤操作”的坑。1.2 初始化配置必須一次做對的三件事裝完Git之后第一件事不是急著clone而是把本機(jī)身份配好。很多人跳過這一步結(jié)果提交記錄里出現(xiàn)一堆“unknown”或者個(gè)人信息亂填的歷史后面再改非常麻煩。git config --global user.name Your Name git config --global user.email youexample.com這兩條命令設(shè)置的user.name和user.email會(huì)寫進(jìn)每次提交的元數(shù)據(jù)里就是你提交記錄上的署名。Git配置分三個(gè)層級--system整臺機(jī)器、--global當(dāng)前用戶、--local當(dāng)前倉庫優(yōu)先級從低到高。也就是說你可以在某個(gè)特定倉庫里用git config --local user.email覆蓋全局郵箱適合那種公司項(xiàng)目和個(gè)人項(xiàng)目需要區(qū)分郵箱的場景。除了身份信息我建議順手做三件初始化配置git config --global init.defaultBranch main git config --global pull.rebase false git config --global core.quotepath false第一個(gè)是把新建倉庫的默認(rèn)分支名設(shè)成main而不是老舊的master新項(xiàng)目和托管平臺的默認(rèn)分支保持一致能省掉很多“為什么我這分支叫master你叫main”的問題。第二個(gè)是pull的時(shí)候默認(rèn)用merge而不是rebase這個(gè)具體差異后面章節(jié)細(xì)說先記住默認(rèn)值就好。第三個(gè)是讓Git顯示中文文件名時(shí)不轉(zhuǎn)義成\xxx的一串亂碼。1.3 容易被忽略的三個(gè)隱藏坑換行符、憑證、編輯器Windows用戶最容易踩的隱藏坑是換行符。Windows系統(tǒng)文件換行是CRLF而Linux/macOS和大部分托管平臺使用LF如果不做處理你提交一個(gè)文本文件Git會(huì)提示整個(gè)文件都被修改了因?yàn)槊恳恍薪Y(jié)尾都變了。解決方案是設(shè)置core.autocrlf。git config --global core.autocrlf true # WindowsWindows上建議設(shè)成true意思是檢出代碼時(shí)自動(dòng)把LF轉(zhuǎn)成CRLF提交時(shí)自動(dòng)轉(zhuǎn)回LF。macOS/Linux用戶則不需要特意設(shè)置或者設(shè)成input保證提交的永遠(yuǎn)是LF。另一個(gè)坑是憑證存儲(chǔ)。如果你用HTTPS方式clone倉庫每次push都要輸賬號密碼開發(fā)效率直線下降。Windows上Git安裝時(shí)默認(rèn)會(huì)啟用managermacOS上會(huì)用osxkeychainLinux可以設(shè)git config --global credential.helper store但store模式是明文存密碼安全性一般。我個(gè)人的建議是能用SSH key就用SSH key這才是遠(yuǎn)程協(xié)作的正解后面第4章會(huì)詳細(xì)講。至于默認(rèn)編輯器只影響你git commit不寫-m參數(shù)時(shí)彈出的編輯界面Vim對新手很不友好可以設(shè)成nano或者你熟悉的編輯器。這些都配好之后你再去clone和commit體感會(huì)完全不同。2. 本地倉庫的完整命令鏈init到commit之間發(fā)生了什么2.1 三個(gè)區(qū)域模型工作區(qū)、暫存區(qū)、版本庫Git之所以讓新手恐懼是因?yàn)樗蛡鹘y(tǒng)“CtrlS保存就完事”的版本管理不一樣引入了“暫存區(qū)”這個(gè)概念。你把一個(gè)文件add進(jìn)去再commit中間其實(shí)隔了一層。我用倉庫打包發(fā)貨來類比**工作區(qū)Working Directory**是你手里正在編輯的貨品**暫存區(qū)Index/Staging Area**是打包臺上的待發(fā)貨紙箱你把貨品放進(jìn)紙箱但不等于已經(jīng)發(fā)走**版本庫Repository**是物流倉庫commit才是真正把紙箱入庫、登記編號。很多人以為git add等于保存其實(shí)add只代表“我打算把這批文件納入下一版提交”真正生成歷史快照的是commit。理解了這個(gè)模型再看git status的輸出就不會(huì)懵。狀態(tài)大致分四種狀態(tài)含義常見操作Untracked新文件還沒被Git管理git addModified已跟蹤文件被改動(dòng)但未暫存git add或git restoreStaged改動(dòng)已放入暫存區(qū)git commit或git restore --stagedClean工作區(qū)與暫存區(qū)、版本庫一致無需操作2.2 高頻增刪改查命令與它們的真實(shí)意圖日常開發(fā)中最常用的命令組合就是add - commit - push - pull但每個(gè)命令內(nèi)部都有值得細(xì)摳的點(diǎn)。先說git add。多數(shù)人都用git add .一把梭把所有改動(dòng)加入暫存區(qū)。但在一個(gè)改動(dòng)較多的項(xiàng)目里我強(qiáng)烈建議用git add -p它以交互方式讓你逐段確認(rèn)哪些改動(dòng)需要暫存。好處很明顯你能避免把調(diào)試用的臨時(shí)日志、無意的修改混進(jìn)同一個(gè)提交提交記錄按功能拆得干凈出問題時(shí)回滾也精準(zhǔn)。尤其在做代碼評審的團(tuán)隊(duì)提交粒度清晰能少挨不少批評。然后是git commit。命令本身有兩種寫法git commit -m fix: 修復(fù)登錄超時(shí)跳轉(zhuǎn)問題寫提交信息時(shí)我習(xí)慣遵循“前綴主題”的規(guī)范feat新功能、fix修bug、docs文檔、refactor重構(gòu)、test測試。這不算什么強(qiáng)制標(biāo)準(zhǔn)但半年后回看歷史時(shí)一眼能看出每個(gè)提交做了什么比寫“更新”兩個(gè)字有用得多。查詢歷史的命令也有講究。git log --oneline --graph --all git log -p --follow -- path/to/file第一條用一行摘要加圖形方式顯示完整歷史方便看分支走向第二條查看某個(gè)文件的修改歷史--follow能跟蹤文件改名后的歷史找“這個(gè)配置參數(shù)是誰改的”時(shí)非常有用。還有兩個(gè)高頻命令git diff默認(rèn)顯示工作區(qū)與暫存區(qū)的差異git diff --staged顯示暫存區(qū)與最近一次提交的差異提交前必須看一遍確認(rèn)沒有把不該提交的東西帶進(jìn)去。刪除文件用git rm重命名用git mv比先刪再加要清晰得多。2.3 撤銷誤操作的三層防線撤銷算是Git的“后悔藥”你要明白每個(gè)后悔藥對應(yīng)的是哪一層狀態(tài)。第一層文件改壞了但還沒add想恢復(fù)到暫存區(qū)或上次提交的狀態(tài)。git restore file.txt這條命令會(huì)把工作區(qū)文件恢復(fù)到暫存區(qū)的樣子。如果你連暫存區(qū)也不想保留先git restore --staged再git restore或者一條git restore --worktree --staged file.txt直接兩手抓。第二層已經(jīng)add到暫存區(qū)想取消暫存。git restore --staged file.txt注意這不會(huì)改文件內(nèi)容只是讓文件回到“未暫存”狀態(tài)。第三層已經(jīng)commit了想撤銷提交。git reset --soft HEAD~1 # 只回退提交記錄保留暫存區(qū) git reset --mixed HEAD~1 # 回退提交記錄和暫存區(qū)保留工作區(qū) git reset --hard HEAD~1 # 全部回退工作區(qū)文件也變回提交前這里有一個(gè)我踩過的坑在共享分支上不要用git reset --hard。因?yàn)樘峤灰呀?jīng)推到遠(yuǎn)程你本地回退了遠(yuǎn)程還留著之前的記錄下一次push會(huì)直接沖突強(qiáng)制推送--force則可能導(dǎo)致同事的更新被覆蓋。如果想撤銷已經(jīng)推送的提交正確做法是git revert它在歷史里生成一個(gè)反向提交其他人拉取后都能同步這個(gè)回滾結(jié)果。如果你真的犯了糊涂把reset --hard也做了還有一個(gè)終極兜底命令git reflog。這個(gè)命令會(huì)列出你本地倉庫所有的頭部移動(dòng)記錄哪怕你重置、切換、誤刪分支都能從reflog里找回原來的HEAD位置。我用它找回過一次誤刪的分支從那以后養(yǎng)成習(xí)慣任何破壞性操作前先看一眼git reflog心里有底。3. 分支合并不是點(diǎn)按鈕沖突根源與解決實(shí)操3.1 分支從創(chuàng)建到合并的標(biāo)準(zhǔn)流程分支是Git的殺手級功能也是新手最容易出事故的地方。標(biāo)準(zhǔn)流程我建議這樣走git switch -c feature/login # 新建并切換分支 # 開發(fā)...提交...推送 git switch main git pull git merge feature/login第一步從main拉一個(gè)功能分支開發(fā)完成后切回main先pull把遠(yuǎn)程最新代碼拉下來再本地合并。順序有講究先pull再merge能減少很多不必要的沖突因?yàn)楹先肽繕?biāo)分支前先讓它保持最新。合并時(shí)會(huì)看到兩種輸出。如果分支的演進(jìn)是直線Git會(huì)執(zhí)行“快進(jìn)合并fast-forward”直接把main的指針挪到feature的提交上歷史是一條線。但如果main在這期間有人提交了Git就會(huì)生成一個(gè)新的Merge commit歷史會(huì)出現(xiàn)分叉再匯合。這兩種結(jié)果本身沒有絕對好壞只是團(tuán)隊(duì)的代碼歷史風(fēng)格偏好。有些團(tuán)隊(duì)嚴(yán)格要求每個(gè)功能合入都保留一個(gè)合并節(jié)點(diǎn)會(huì)用git merge --no-ff feature/login強(qiáng)制生成合并提交。3.2 沖突產(chǎn)生的根源與解決實(shí)操?zèng)_突是所有初學(xué)者最怕的東西但只要理解了它的本質(zhì)其實(shí)不難。沖突的本質(zhì)是同一個(gè)文件的同一個(gè)區(qū)域被兩個(gè)分支以不同的方式修改了。Git能自動(dòng)合并那些互不干擾的改動(dòng)只有當(dāng)它自己也拿不準(zhǔn)該保留誰時(shí)才會(huì)停下來向你求助。我模擬一個(gè)具體例子。你和一個(gè)同事各自從main拉了分支同事改了一個(gè)配置文件config.yml的第20行你也改了同文件第20行 HEAD timeout: 30 timeout: 60 feature/login HEAD到之間是當(dāng)前分支HEAD的內(nèi)容到之間是待合并分支的內(nèi)容。你要做的不是直接刪除標(biāo)記而是先看懂兩邊的意圖。比如同事改timeout: 60是因?yàn)榉?wù)端要求你的30是本地調(diào)試值這種沖突就該保留同事的版本解決好之后再git add config.yml提交沖突合并即可。提示解決沖突時(shí)別關(guān)閉編輯器就完事一定要把、、這些標(biāo)記全部刪干凈否則文件會(huì)帶著Git的沖突標(biāo)記提交上去造成編譯錯(cuò)誤甚至線上事故。沖突解決完執(zhí)行g(shù)it status看到“All conflicts fixed but you are still merging”的提示說明已經(jīng)進(jìn)入提交階段直接git commit結(jié)束本次合并。如果你在解決沖突過程中發(fā)現(xiàn)方向完全錯(cuò)了用git merge --abort可以徹底終止合并回到合并前的狀態(tài)。3.3 merge、rebase、cherry-pick 怎么選這三個(gè)命令都能幫你整理提交歷史但適用場景完全不同。git merge是“匯合”保留各方分支的存在痕跡歷史里有清晰的合并節(jié)點(diǎn)適合團(tuán)隊(duì)多人協(xié)作因?yàn)槭亲芳邮降牟粫?huì)改寫已有提交風(fēng)險(xiǎn)最小。git rebase是“變基”它會(huì)把當(dāng)前分支的提交一個(gè)個(gè)摘下來重新安放到目標(biāo)分支的最新提交之上歷史從分叉變成一條直線。好處是git log非常干凈壞處是提交的提交時(shí)間和原始身份會(huì)被改寫絕對不要對已經(jīng)被推到遠(yuǎn)程、多人共用的分支執(zhí)行rebase否則會(huì)讓所有人的本地歷史都產(chǎn)生裂縫。git cherry-pick則是“摘櫻桃”把另一個(gè)分支上的某一個(gè)或多個(gè)提交精確地復(fù)制到當(dāng)前分支。這個(gè)在線上緊急修復(fù)非常好用開發(fā)分支上有個(gè)修復(fù)bug的提交但功能整體還沒測試完你只想把那個(gè)修復(fù)單獨(dú)搬到main上git cherry-pick commit-id就能做到。我的習(xí)慣是本地個(gè)人分支為了整理歷史用rebase多人共享分支合并一律用merge跨分支撈單個(gè)修復(fù)用cherry-pick。三者的選擇邏輯寫一個(gè)簡單的表供參考操作歷史形狀改寫提交適用場景merge分叉合并否團(tuán)隊(duì)共享分支合入rebase線性是本地整理個(gè)人分支cherry-pick單點(diǎn)復(fù)制是移植特定提交4. SSH認(rèn)證失敗排查鏈路把報(bào)錯(cuò)一步步拆開看4.1 HTTPS與SSH認(rèn)證的差異很多人第一次用Git遠(yuǎn)程協(xié)作時(shí)會(huì)直接復(fù)制托管平臺上的HTTPS地址https://github.com/user/repo.git。這種方式的優(yōu)點(diǎn)是零配置只要首次輸入賬號密碼或訪問令牌就能clone但每次push都要重復(fù)認(rèn)證。而SSH方式則完全不同本地生成一對密鑰公鑰放到代碼托管平臺上以后的所有操作都靠本地私鑰鑒定身份再也不用敲密碼。缺點(diǎn)是初始配置稍微復(fù)雜報(bào)錯(cuò)信息不友好尤其是“Permission denied (publickey)”這類提示絕大多數(shù)人都不知道問題出在哪。4.2 密鑰生成與正確配置先講正確做法。生成密鑰ssh-keygen -t ed25519 -C youremail.com直接回車使用默認(rèn)保存路徑~/.ssh/id_ed25519可以設(shè)置一個(gè)passphrase口令每次使用密鑰時(shí)輸入一次。這個(gè)passphrase是額外保護(hù)萬一筆記本丟了拿到密鑰文件的人也無法直接使用。如果你不想每次都輸口令可以用ssh-add把它加進(jìn)ssh-agenteval $(ssh-agent) ssh-add ~/.ssh/id_ed25519然后把公鑰內(nèi)容id_ed25519.pub文件里的那一長串字符串復(fù)制到代碼托管平臺后臺的“SSH Keys”設(shè)置頁面。這一步經(jīng)常有人搞錯(cuò)把私鑰id_ed25519內(nèi)容復(fù)制給了平臺。私鑰相當(dāng)于你的身份證絕不能外傳平臺上放的是公鑰。復(fù)制時(shí)仔細(xì)看清楚文件名后綴是.pub。配置完成后測試ssh -T gitgithub.com如果看到類似“Hi username! Youve successfully authenticated”的返回說明認(rèn)證鏈路通了。如果報(bào)錯(cuò)踩到的問題基本都在下面。4.3 SSH認(rèn)證失敗的完整排查路徑我整理了一份每次遇到Permission denied (publickey)時(shí)就照著走的排查清單基本能覆蓋90%的情況。第一步先看詳細(xì)日志把錯(cuò)誤信息放大看ssh -vT gitgithub.com日志里會(huì)顯示Git在嘗試加載哪些密鑰文件、訪問哪個(gè)地址。重點(diǎn)看類似Offering public key和Authentications that can continue的部分。如果日志里根本沒有嘗試加載密鑰多半是你指定的密鑰路徑不對或者私鑰文件權(quán)限過寬Unix系統(tǒng)要求私鑰文件權(quán)限不能高于600。第二步檢查你是否真的把公鑰加到了平臺上。很多人換電腦后重新生成了密鑰但忘了解除舊公鑰、添加新公鑰。到托管平臺的SSH Keys頁面核對公鑰指紋本地用ssh-keygen -lf ~/.ssh/id_ed25519.pub查看指紋兩者應(yīng)一致。第三步確認(rèn)遠(yuǎn)程地址確實(shí)是SSH格式而不是HTTPS。git remote -v如果顯示https://...開頭說明SSH認(rèn)證根本沒參與這次操作。改成SSH格式即可git remote set-url origin gitgithub.com:user/repo.git第四步處理多賬戶場景。比如你同時(shí)用同一個(gè)Git客戶端連接公司的GitLab和個(gè)人GitHub默認(rèn)會(huì)使用同一個(gè)密鑰導(dǎo)致有一邊必然認(rèn)證失敗。解決辦法是在~/.ssh/config里顯式指定不同主機(jī)的密鑰文件Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitlab.company.com HostName gitlab.company.com User git IdentityFile ~/.ssh/id_ed25519_company還有一類報(bào)錯(cuò)是Host key verification failed這通常是首次連接遠(yuǎn)程主機(jī)時(shí)本地沒有緩存對方的服務(wù)器指紋。解決辦法是按提示輸入yes接受并緩存或者如果頻繁提示檢查本機(jī)Agent緩存。整體思路就一句話從日志里找它加載了哪個(gè)密鑰指到哪個(gè)地址然后逐一核對“本地密鑰是否生成、私鑰權(quán)限是否合適、平臺公鑰是否匹配、遠(yuǎn)程URL是否走SSH”這四個(gè)環(huán)節(jié)。5. 遠(yuǎn)程項(xiàng)目拉取、推送與回滾日常協(xié)作中最高頻的場景5.1 fetch、pull、push的區(qū)別與遠(yuǎn)程跟蹤分支遠(yuǎn)程協(xié)作有一個(gè)基礎(chǔ)概念必須先弄懂本地分支和遠(yuǎn)程分支其實(shí)是兩套副本。遠(yuǎn)程倉庫在你clone時(shí)默認(rèn)叫做origin遠(yuǎn)程的main分支在本地Git里叫origin/main這是一個(gè)遠(yuǎn)程跟蹤分支只記錄“我上次從遠(yuǎn)程看到的位置”你并不能直接在上面工作。三個(gè)命令的區(qū)別命令行為git fetch只下載遠(yuǎn)程的新提交不改變工作區(qū)git pull等于fetch merge更新工作區(qū)git push把本地提交上傳到遠(yuǎn)程我見過很多人把git pull當(dāng)成“刷新按鈕”一有報(bào)錯(cuò)就反復(fù)pull其實(shí)pull內(nèi)部做了兩件事下載遠(yuǎn)程更新合并到當(dāng)前分支。如果你本地有未推送的提交而遠(yuǎn)程也前進(jìn)了pull就會(huì)產(chǎn)生一個(gè)合并提交或沖突未必是好事。更穩(wěn)妥的做法是先git fetch然后對比git log origin/main..main看本地領(lǐng)先多少再?zèng)Q定是否pull或rebase。推送新分支時(shí)有個(gè)細(xì)節(jié)值得注意第一次推送需要設(shè)上游讓本地分支和遠(yuǎn)程分支建立跟蹤關(guān)系。git push -u origin feature/login之后你在這個(gè)分支上直接git push和git pull就能正常工作不需要每次指定遠(yuǎn)端和分支名。日常clone項(xiàng)目更簡單git clone gitgithub.com:user/repo.git克隆完成后倉庫會(huì)自動(dòng)關(guān)聯(lián)origin目錄名默認(rèn)是倉庫名也可以額外指定目錄名git clone url my-project。5.2 提交信息規(guī)范與緊急回滾思路線上出了bug需要緊急回滾時(shí)最怕的就是提交歷史混亂。所以提交信息規(guī)范不只是給別人看更是給“未來遇到線上事故的自己”看的。遵循“動(dòng)詞前綴短句”的格式回滾時(shí)定位提交會(huì)非????;貪L又分兩種場景。如果你還沒有把壞提交推到遠(yuǎn)程本地直接git reset --hard HEAD~1然后重新提交就行。如果你已經(jīng)推送了那么用git revert commit-id生成一個(gè)反向提交再push歷史上會(huì)留下“這次提交被撤銷”的記錄。revert不會(huì)刪除原提交但能確保共享分支上的同事拉取后自動(dòng)同步到已回滾的狀態(tài)。這里有個(gè)實(shí)操技巧git revert默認(rèn)會(huì)彈出編輯器要求填寫提交信息你可以用git revert -m 1 merge-commit-id處理合并提交的回滾-m 1表示保留合并的第一父分支即主分支的內(nèi)容。具體場景復(fù)雜建議先在本地臨時(shí)分支演練一遍別直接在線上生產(chǎn)分支上手。5.3 IDE中拉取Git項(xiàng)目與可視化解決沖突熱搜里出現(xiàn)了“diea創(chuàng)建新項(xiàng)目拉取git”這里說的其實(shí)是IntelliJ IDEA從版本控制拉取項(xiàng)目。日常開發(fā)中如果你主要用IDE確實(shí)可以不完全依賴命令行但核心模型一定要聽得懂否則IDE報(bào)錯(cuò)時(shí)照樣抓瞎。IDEA的操作路徑是菜單File - New - Project from Version Control在URL欄粘貼倉庫地址選擇存放目錄點(diǎn)Clone。IDEA會(huì)自己識別出這是Git項(xiàng)目自動(dòng)進(jìn)入分支管理面板。之后你可以在Git工具窗口里看到所有分支、提交歷史、以及本地與遠(yuǎn)程的狀態(tài)差異沖突文件也會(huì)用三欄對比視圖展示左欄是本地版本、中間是合并結(jié)果、右欄是遠(yuǎn)程版本手動(dòng)點(diǎn)擊箭頭就能選取內(nèi)容。我個(gè)人的習(xí)慣是日常提交用IDE的可視化界面因?yàn)槟芸吹轿募壊町悳p少把不相關(guān)文件混在一起的幾率但遇到?jīng)_突、重構(gòu)、分支整理這種復(fù)雜操作我更喜歡切到終端因?yàn)槊钚心芫_控制每一步比如git add -p的逐段暫存、git rebase -i的交互式整理都不是IDE按鈕能完全替代的。還有一個(gè)日常高頻場景IDE里拉取遠(yuǎn)程更新時(shí)如果本地有未提交的修改容易被pull擋住。先git stash把當(dāng)前改動(dòng)暫存起來pull完成后再git stash pop取回這個(gè)組合我?guī)缀趺恐芏加谩E紶杝tash pop也會(huì)沖突但至少改動(dòng)不會(huì)丟失比強(qiáng)制覆蓋安全得多。最后再分享一個(gè)我后來才學(xué)會(huì)的習(xí)慣無論用命令行還是IDE在推送任何“可能影響別人”的改動(dòng)之前先看一眼git status和git log --oneline -3。多花十秒鐘確認(rèn)自己站在正確的分支、手頭改動(dòng)確實(shí)該提交能省掉后面一小時(shí)的救火時(shí)間。Git的命令不算少但真正每天都在用的其實(shí)就那二三十個(gè)把它們的層級模型和意圖理解透比背下整本手冊管用得多。