
做開發(fā)這些年幾乎每天都要跟 Git 打交道。不管是個(gè)人維護(hù)開源項(xiàng)目還是團(tuán)隊(duì)協(xié)作改一個(gè)線上服務(wù)版本管理都是繞不開的一環(huán)。Git 之所以能成為事實(shí)標(biāo)準(zhǔn)不在于命令多而在于它的核心工作流足夠順手改代碼、提交、分支、合并、推送一套動(dòng)作下來版本就有了清晰的歷史脈絡(luò)。這篇內(nèi)容就以 Git 基本工作流為主線把安裝配置、日常命令、分支協(xié)作、沖突處理和那些讓人頭疼的疑難雜癥都過一遍適合剛把 Git 裝好、還沒完全上手的同學(xué)也適合用了很久但老是靠“背命令”過日子的老兄——看完你會(huì)知道每條命令背后到底在做什么。很多人學(xué) Git 卡住不是因?yàn)槊铍y而是因?yàn)槟X子里沒有一張“圖”。Git 不像 SVN 那樣只有“中心倉庫”和“工作副本”兩個(gè)概念它把人搞暈的恰恰是本地也有完整版本庫這件事。所以我不打算上來就扔一張命令清單而是先帶你建立工作流的整體認(rèn)知再一步步拆解每個(gè)環(huán)節(jié)的細(xì)節(jié)和坑。這樣后面無論遇到什么奇怪報(bào)錯(cuò)你都能自己定位問題。1. 先把基礎(chǔ)打好Git 安裝與環(huán)境配置1.1 不同系統(tǒng)的安裝方式先說裝 Git。這一步看著簡單但很多人裝完發(fā)現(xiàn)命令行里敲git沒反應(yīng)或者 IDE 里顯示 Git 路徑不對(duì)全是安裝時(shí)埋下的雷。Windows 用戶最穩(wěn)妥的方式是去 Git 官網(wǎng)下載安裝包。裝的時(shí)候有幾個(gè)選項(xiàng)值得注意一是“Adjusting your PATH environment”默認(rèn)推薦的第二項(xiàng)“Git from the command line and also from 3rd-party software”一定要選這樣你在 CMD、PowerShell 和 IDE 里都能直接調(diào)用 git二是“Checkout style”里選“Checkout Windows-style, commit Unix-style line endings”這是默認(rèn)值能避免大部分換行符問題。安裝包體積不大裝完打開 PowerShell 輸入git --version能輸出版本號(hào)就算成功了。如果提示“無法將‘git’項(xiàng)識(shí)別為 cmdlet、函數(shù)、腳本文件或可運(yùn)行程序的名稱”多半是 PATH 沒生效重開終端或注銷一次就行。macOS 上有三條路用 Xcode Command Line Tools、用 Homebrew、用官網(wǎng) dmg。最省心的是 Homebrew一條brew install git就完事以后升級(jí)也方便。Linux 各發(fā)行版則用自帶包管理器Ubuntu/Debian 是sudo apt install gitCentOS/RHEL 是sudo yum install git。無論是哪種系統(tǒng)裝完第一件事永遠(yuǎn)是git --version確認(rèn)。還有一個(gè)很多人忽略的點(diǎn)如果你用的是 IDEA、VS Code 這類 IDE它們內(nèi)置的 Git 插件不一定走系統(tǒng) PATH。遇到“無法找到 Git 可執(zhí)行文件”的提示去 IDE 的版本控制設(shè)置里手動(dòng)定位git.exe或/usr/bin/git路徑就行。macOS 上裝了 IDEA 但識(shí)別不到 Git常見原因就是沒裝 Xcode Command Line Tools裝完就好了。1.2 裝完必做的三件事安裝只是開始真正決定你后續(xù)體驗(yàn)的是配置。這里說的配置不是那些花里胡哨的別名而是最基本的用戶信息、換行符和默認(rèn)文本編輯器。用戶信息是提交記錄的“簽名”沒配的話每次 commit 都會(huì)報(bào)錯(cuò)。打開終端執(zhí)行g(shù)it config --global user.name 你的名字 git config --global user.email 你的郵箱注意這里的郵箱最好和你的代碼托管平臺(tái)Gitee、GitHub、GitLab綁定郵箱一致這樣提交記錄能正確關(guān)聯(lián)到你的賬號(hào)。--global表示對(duì)當(dāng)前用戶全局生效如果某個(gè)特定倉庫想用不同的身份可以在那個(gè)倉庫目錄下去掉--global再設(shè)置一次。換行符問題我多說兩句。Windows 默認(rèn)換行符是 CRLFLinux/macOS 是 LF。如果不處理同一個(gè)文件在 Windows 和 Linux 之間來回 checkout 時(shí)Git 會(huì)認(rèn)為整個(gè)文件都改了diff 直接爆炸。我在前面提到的安裝默認(rèn)選項(xiàng)就能解決大部分問題。如果你已經(jīng)裝完了也沒關(guān)系手動(dòng)設(shè)置一下git config --global core.autocrlf true # Windows 用戶 git config --global core.autocrlf input # Linux/macOS 用戶這樣一來Git 在 Windows 上 checkout 時(shí)會(huì)把 LF 轉(zhuǎn)成 CRLF提交時(shí)再轉(zhuǎn)回 LF倉庫里永遠(yuǎn)存的是 LF跨平臺(tái)協(xié)作就不會(huì)互相傷害了。1.3 賬號(hào)憑據(jù)與免密配置配置好身份后下一步是讓 Git 記住你的賬號(hào)不然每次 push/pull 都輸密碼用不了幾次就煩了。先說 HTTPS 方式。Windows 上裝 Git 時(shí)會(huì)默認(rèn)啟用“Git Credential Manager”第一次輸入賬號(hào)密碼后會(huì)被安全存在 Windows 憑據(jù)管理器里之后自動(dòng)免密。如果發(fā)現(xiàn)沒生效可以手動(dòng)開啟git config --global credential.helper managermacOS 則用osxkeychaingit config --global credential.helper osxkeychainLinux 可以選擇store純文本存用戶目錄不推薦在共享機(jī)器上用或者cache只緩存內(nèi)存一段時(shí)間。我個(gè)人在 Linux 服務(wù)器上更習(xí)慣用 SSH 方式后面一節(jié)細(xì)說。要清除已經(jīng)保存的賬號(hào)密碼Windows 可以去“控制面板-憑據(jù)管理器”里刪除對(duì)應(yīng)的 git 憑據(jù)或者用命令git credential-manager github logout git credential-manager eraseVS Code 里如果你發(fā)現(xiàn)總是彈出登錄框、反復(fù)讓你輸密碼多半是憑據(jù)管理器沒配好。先把git config --global --list拿出來看一眼確認(rèn) credential.helper 有值再測試一次 push 讓它記住就好。1.4 SSH 密鑰配置與認(rèn)證失敗排查SSH 的好處是一旦配好密鑰所有 Git 操作都免密而且更安全。生成密鑰很簡單ssh-keygen -t ed25519 -C 你的郵箱一路回車會(huì)在~/.ssh/id_ed25519.pub生成公鑰。然后把公鑰內(nèi)容添加到 Gitee 或 GitHub 的“SSH 公鑰”設(shè)置里。添加完成后測試ssh -T gitgitee.com如果看到歡迎信息說明密鑰沒問題。這里有個(gè)常見的坑克隆倉庫時(shí)用了 HTTPS 地址但你把密鑰配到了 SSH 上那自然還得輸密碼。另外在 Gitee 上正確的主機(jī)名是gitee.com端口默認(rèn) 22 不通的時(shí)候可以試 443 端口ssh -T -p 443 gitssh.gitee.com“ssh認(rèn)證失敗”這類問題我排過很多次80% 是三種原因公鑰沒加到平臺(tái)、克隆地址用錯(cuò)HTTPS/SSH搞混、本地有多個(gè)密鑰導(dǎo)致 Git 用了錯(cuò)誤的私鑰。第三種可以用~/.ssh/config指定某個(gè) host 使用哪個(gè)密鑰文件Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519寫完這個(gè)配置記得chmod 600一下私鑰文件不然權(quán)限太開放SSH 會(huì)拒絕使用。2. 基本工作流核心工作區(qū)、暫存區(qū)與提交2.1 先理解三個(gè)區(qū)域和文件狀態(tài)我一直覺得Git 的命令記不住本質(zhì)上是因?yàn)椴焕斫馑盐募鸪闪巳齻€(gè)區(qū)域工作區(qū)Working Directory、暫存區(qū)Index/Staging Area和本地倉庫Repository。工作區(qū)是你編輯器里看到的文件暫存區(qū)是一個(gè)臨時(shí)存放“準(zhǔn)備提交的改動(dòng)”的地方本地倉庫才是真正記錄歷史的地方。這套設(shè)計(jì)和 SVN 最大的區(qū)別在于SVN 只有“提交”一步而 Git 把“準(zhǔn)備提交”和“真正提交”分開了。這個(gè)設(shè)計(jì)的好處是你可以只提交一部分改動(dòng)、把另一部分繼續(xù)留在工作區(qū)方便按邏輯拆分成多個(gè) commit。壞處是新手上手時(shí)容易懵為什么git status里文件有的是紅色、有的是綠色紅的代表有改動(dòng)但還沒暫存綠的表示已經(jīng)加入到暫存區(qū)、等待提交。理解了這個(gè)再看git status就很簡單了。那些“Changes not staged for commit”就是工作區(qū)的改動(dòng)“Changes to be committed”就是暫存區(qū)的改動(dòng)。日常操作過程中我會(huì)習(xí)慣每隔幾分鐘就跑一次git status它會(huì)把當(dāng)前倉庫狀態(tài)、當(dāng)前分支、有哪些修改全部告訴你是排查問題的最好入口。2.2 日常提交循環(huán)add、commit、status、log一次完整的本地提交流程是這樣git status # 查看狀態(tài) git diff # 查看具體改動(dòng)內(nèi)容 git add file # 把文件加入暫存區(qū) git commit -m 提交說明 # 提交到本地倉庫git add的粒度可以很靈活。你可以git add .把所有改動(dòng)加進(jìn)去也可以只git add src/xxx.js只提交某個(gè)文件還可以用git add -p交互式地把一個(gè)文件里的不同代碼塊拆開提交。最后這個(gè)技能非常實(shí)用因?yàn)椤耙粋€(gè) commit 只做一件事”是好習(xí)慣但實(shí)際開發(fā)時(shí)經(jīng)常會(huì)一個(gè)文件里改了多處不同邏輯用-p就能手動(dòng)分割。commit 信息的寫法也有講究。我見過最頭疼的提交信息是“fix bug”或“修改”等過三個(gè)月回看歷史完全不知道當(dāng)時(shí)改了什么。我個(gè)人的習(xí)慣是第一行用一句祈使句概括動(dòng)作比如“修復(fù)訂單金額計(jì)算精度問題”如果改動(dòng)較大就空一行再寫一段詳細(xì)說明說明里交代“為什么這么改”而不是復(fù)述代碼改了什么。這種寫法在git log --oneline里看得特別清楚。git log還有幾個(gè)好用的參數(shù)git log --oneline -5看最近五次簡明記錄git log --stat看每次提交改了哪些文件git log -p直接看 diff。我排查問題時(shí)最常用的是git log -S某個(gè)關(guān)鍵詞它能找出“哪個(gè) commit 新增或刪除了包含某個(gè)關(guān)鍵詞的行”這在定位歷史 bug 時(shí)簡直救命。2.3 從遠(yuǎn)程拉取項(xiàng)目clone 與 IDE 集成進(jìn)入團(tuán)隊(duì)協(xié)作的第一步通常是拉取遠(yuǎn)程倉庫對(duì)應(yīng)命令是git clone 倉庫地址 [目錄名]這里的地址可以是 HTTP 也可以是 SSH。我在前面強(qiáng)調(diào)過如果已經(jīng)配好了 SSH 密鑰就用 SSH 地址一勞永逸。clone 完成后Git 會(huì)把遠(yuǎn)程倉庫完整下載下來并自動(dòng)建立名為origin的遠(yuǎn)程別名和本地的主分支同時(shí)切換到本地分支上。IDE 集成方面IDEA 里新建項(xiàng)目從 Git 拉取很簡單File → New → Project from Version Control粘貼倉庫地址一路下一步。VS Code 則是在源代碼管理面板里選“克隆倉庫”。我自己的經(jīng)驗(yàn)是不要在 IDE 里用不熟悉的圖形化按鈕操作分支合并等命令用熟了再回去用圖形界面心里會(huì)踏實(shí)很多。IDE 的 Git 面板適合看狀態(tài)、看 diff、做 commit但分支操作和沖突解決命令行反而更清晰。一個(gè)經(jīng)常踩的坑是克隆時(shí)如果倉庫里有 Git LFS 大文件而本地沒裝 LFS文件會(huì)被拉成一個(gè)幾 KB 的文本指針真正的文件內(nèi)容不會(huì)下載。遇到這種情況先安裝 Git LFS再執(zhí)行g(shù)it lfs pull手動(dòng)拉取。后面我會(huì)專門講 LFS。2.4 本地項(xiàng)目接入遠(yuǎn)程倉庫的流程不是所有情況都需要 clone。很多時(shí)候是你先在本地寫了一堆代碼還沒建遠(yuǎn)程倉庫現(xiàn)在要把整個(gè)項(xiàng)目推上去。流程其實(shí)很固定。以 Gitee 為例先在網(wǎng)頁端創(chuàng)建一個(gè)空倉庫不要勾選“初始化倉庫”選項(xiàng)然后回到本地項(xiàng)目目錄git init # 把當(dāng)前目錄變成 Git 倉庫 git add . git commit -m 初始提交 git branch -M main # 把當(dāng)前分支改名為 main git remote add origin 倉庫地址 git push -u origin main # 推送到遠(yuǎn)程并設(shè)置上游關(guān)聯(lián)如果遠(yuǎn)程倉庫在網(wǎng)頁端已經(jīng)初始化過生成了 README、.gitignore 等本地直接git push會(huì)報(bào)錯(cuò)“refusing to merge unrelated histories”。這時(shí)候有兩個(gè)選擇一是接受遠(yuǎn)程已有的初始化內(nèi)容先把遠(yuǎn)程內(nèi)容拉下來再合并二是你確認(rèn)遠(yuǎn)程是空倉庫強(qiáng)制推上去git pull origin main --allow-unrelated-histories # 或者你覺得遠(yuǎn)程那個(gè)初始提交沒意義反過來覆蓋它 git push -u origin main --force--force是危險(xiǎn)操作會(huì)覆蓋遠(yuǎn)端歷史團(tuán)隊(duì)協(xié)作時(shí)慎用如果是自己一個(gè)人用剛建的空倉庫就沒那么敏感。但我建議就算是一個(gè)人也要先想清楚再 force形成習(xí)慣后將來就不至于在別人沒注意的時(shí)候把同事的提交沖掉。3. 分支合并是協(xié)作的命脈3.1 分支的創(chuàng)建、切換與合并分支是 Git 最值得炫耀的功能。它本質(zhì)上只是一個(gè)指向某次提交的指針?biāo)詣?chuàng)建分支的成本幾乎為零這也是 Git 和 SVN 在協(xié)作模型上最大的差異SVN 的分支是目錄拷貝又慢又占空間Git 的分支就是一張便利貼隨時(shí)貼隨時(shí)撕。基礎(chǔ)操作就三個(gè)git branch feature/login # 創(chuàng)建分支 git checkout feature/login # 切換分支 git switch feature/login # 切換分支新版推薦git switch是 Git 2.23 之后推薦使用的命令語義上比checkout清晰。但服務(wù)器和老教程里常見checkout所以兩種都要認(rèn)得。創(chuàng)建并切換一步到位用git switch -c feature/login或git checkout -b feature/login。合并分支時(shí)推薦一個(gè)我用了很久的保守策略先把主分支更新到最新再切回功能分支把主分支合并進(jìn)來或者用 rebase后面說解決掉所有沖突最后再切回主分支做合并。這樣能讓主分支始終保持干凈的歷史沖突也更容易定位。git checkout main git pull origin main # 確保主分支是最新 git checkout feature/login git merge main # 把主分支的新內(nèi)容并入功能分支 git checkout main git merge feature/login # 功能開發(fā)完合并回主分支 git push origin main這里要提醒一個(gè)新手常見的操作失誤在主分支上直接改代碼忘記先開功能分支。等你 push 的時(shí)候才發(fā)現(xiàn)和別人的改動(dòng)全攪在一起。每次開始新功能前先問自己一句“我現(xiàn)在在哪個(gè)分支”這是一個(gè)值得養(yǎng)成肌肉記憶的操作習(xí)慣。3.2 merge 與 rebase 的選擇合并分支有兩條路merge和rebase。這倆經(jīng)常爭得不可開交我講清楚區(qū)別你自己選。merge會(huì)生成一個(gè)額外的“合并提交”保留了兩個(gè)分支真實(shí)的匯合點(diǎn)歷史是網(wǎng)狀的能看出來“這里并進(jìn)來過一件事”。優(yōu)點(diǎn)是不改動(dòng)已有提交安全缺點(diǎn)是歷史圖不太直時(shí)間長了會(huì)亂。rebase會(huì)把當(dāng)前分支的提交“拆下來”一個(gè)一個(gè)重新打到目標(biāo)分支的頂端上歷史變成一條直線。優(yōu)點(diǎn)是干凈整潔缺點(diǎn)是它會(huì)改寫提交的哈希和時(shí)間屬于“改寫歷史”的操作千萬不要在已經(jīng)推送出去、別人也在用的分支上隨便 rebase。我個(gè)人的習(xí)慣是還沒有推送到遠(yuǎn)程的本地功能分支用 rebase 把主分支的新更新整合進(jìn)來已經(jīng)推送到遠(yuǎn)程、并且涉及多人協(xié)作的分支老老實(shí)實(shí)用 merge 或創(chuàng)建新的合并請(qǐng)求。一句話公共分支上別 rebase私有分支上隨便玩。3.3 沖突的產(chǎn)生和解決流程沖突是 Git 協(xié)作里繞不過去的坎也是很多人最怕的東西。其實(shí)沖突的本質(zhì)就是 Git 無法自動(dòng)決定到底聽誰的需要人來判斷。最典型的場景是 A、B 兩個(gè)人同時(shí)改了同一個(gè)文件的同一行。B 在 merge 時(shí)會(huì)看到這樣的標(biāo)記 HEAD 當(dāng)前分支的內(nèi)容 被合并分支的內(nèi)容 feature/login這個(gè)標(biāo)記把沖突區(qū)域圈出來了到是當(dāng)前分支的版本到是外來分支的版本。你在編輯器里把它改成最終想要的樣子刪掉那三行標(biāo)記保存文件然后git add 解決完的文件 git commit沖突解決完成。整個(gè)過程 Git 不會(huì)替你決定“保留誰”只會(huì)把選擇權(quán)交給你。我見過很多新手在沖突時(shí)慌不擇路亂刪標(biāo)記導(dǎo)致文件語法錯(cuò)誤。建議記住一個(gè)原則先讀代碼理解兩邊各自的意圖而不是“誰的代碼留下來”。如果兩個(gè)人改的是同一個(gè)邏輯更穩(wěn)妥的方式是把兩邊的人叫到一起確認(rèn)最終的實(shí)現(xiàn)再合并。沖突本身也不是壞事它說明團(tuán)隊(duì)確實(shí)在同一塊業(yè)務(wù)上投入了兩股不同的力只是需要一個(gè)明確的主導(dǎo)者。另一個(gè)減少?zèng)_突頻率的操作是功能分支存活時(shí)間不要太長。一個(gè)分支拖了三周主分支早就翻天覆地合并回來時(shí)的沖突規(guī)模肯定讓人崩潰。小而短的分支是 Git 協(xié)作最健康的節(jié)奏。3.4 修改歷史amend 與交互式 rebasegit commit --amend是我平時(shí)用得挺多的一個(gè)命令。它的作用是修改“最近一次提交”可以改提交信息也可以把當(dāng)前暫存區(qū)的改動(dòng)偷偷塞進(jìn)上一次提交里。比如我寫完一個(gè) commit 后發(fā)現(xiàn)少了個(gè)文件或者提交信息寫錯(cuò)了字git add 遺漏的文件 git commit --amend執(zhí)行完會(huì)打開編輯器讓你改提交信息如果只是想保留原有信息、只補(bǔ)充文件可以用git commit --amend --no-edit。但注意amend同樣會(huì)改寫提交哈希。如果這個(gè) commit 已經(jīng) push 到遠(yuǎn)程了而且有別人拉下來過就不要 amend 了不然下次 push 會(huì)被拒絕你不得不再走一次 force push很可能擾亂別人的倉庫。想改更早的歷史用交互式 rebasegit rebase -i HEAD~3界面會(huì)列出最近三個(gè)提交你可以在每個(gè)提交前改成pick、squash合并到前一個(gè)、edit停下來修改、reword改信息等操作。這個(gè)功能很強(qiáng)大但建議只在本地分支上用。我自己的用法是在把功能分支推到遠(yuǎn)程前用交互式 rebase 把一堆零散的“wip”“fix typo”壓縮成一個(gè)干凈完整的提交這樣合并請(qǐng)求里看到的歷史就很清晰。4. 大文件、效率工具與倉庫維護(hù)4.1 Git LFS大文件管理的正確姿勢普通 Git 倉庫是為文本設(shè)計(jì)的把所有文件的歷史都存在.git目錄里。如果倉庫里混入了大文件比如設(shè)計(jì)稿、模型、數(shù)據(jù)集每次修改都會(huì)讓倉庫體積瘋狂變大clone 一次慢到懷疑人生。Git LFSLarge File Storage就是解決這個(gè)問題的它把大文件的實(shí)際內(nèi)容移到遠(yuǎn)程服務(wù)端倉庫里只保留一個(gè)幾十字節(jié)的指針文件需要真實(shí)內(nèi)容時(shí)再按需下載。安裝和使用都很簡單git lfs install git lfs track *.psd git lfs track *.zip git add .gitattributes之后這些類型的大文件提交、推送、拉取都由 LFS 接管??寺∫粋€(gè)帶 LFS 的倉庫前確保本地已經(jīng)安裝了相同版本的 Git LFS如果 clone 到一半卡住很可能是某個(gè)大文件特別大Git 正在后臺(tái)下載別急著 CtrlC先看輸出信息。也可以用git lfs clone和git lfs pull來分別處理不過新版 Git 已經(jīng)把 LFS 集成得比較好了。LFS 的坑在于它的數(shù)據(jù)也是有限額的Gitee 免費(fèi)用戶有固定容量和流量限制用超了就拉不動(dòng)。我的建議是能用壓縮包或 CDN 管理的大文件別放進(jìn) Git 倉庫真正需要隨代碼版本走的大文件才進(jìn) LFS。4.2 worktree一個(gè)目錄并行管理多個(gè)分支有時(shí)候你需要同時(shí)開好幾個(gè)分支干活。比如當(dāng)前工作區(qū)正改著某功能臨時(shí)被叫去修復(fù)一個(gè)線上 bug但手頭改動(dòng)還沒提交git switch會(huì)直接阻止你切過去。常規(guī)做法是 stash 暫存當(dāng)前改動(dòng)另一種更清爽的辦法是git worktreegit worktree add ../hotfix bugfix/urgent-fix這條命令會(huì)在../hotfix目錄下新建一個(gè)工作區(qū)專門服務(wù)于bugfix/urgent-fix分支。你可以在這個(gè)新目錄里做緊急修復(fù)、提交、推送完全不影響原目錄里沒提交的改動(dòng)。修完再看git worktree list git worktree remove ../hotfix這個(gè)功能特別適合需要在多個(gè)分支并行發(fā)版、或者經(jīng)常跨分支比對(duì)著改代碼的場景。我用了之后基本擺脫了“切分支前先 stash”的繁瑣流程。4.3 清理、還原與撤銷操作指南Git 操作里撤銷永遠(yuǎn)比提交復(fù)雜。我整理一下不同場景的處理方式如果改了文件但還沒git add想放棄所有改動(dòng)用git checkout -- file # 或者新版寫法 git restore file如果已經(jīng)git add了但還沒 commit想取消暫存文件內(nèi)容保留git reset HEAD file git restore --staged file如果已經(jīng) commit 了想撤掉這次提交但保留改動(dòng)內(nèi)容git reset --soft HEAD~1如果想連改動(dòng)一起丟棄就用git reset --hard HEAD~1這個(gè)操作很危險(xiǎn)改動(dòng)直接沒了。我的建議是執(zhí)行--hard前先把當(dāng)前狀態(tài)存?zhèn)€備份分支或者git stash兜底哪怕操作失誤也能找回。還有一個(gè)高頻場景是.gitignore沒配好把不該提交的目錄比如 node_modules、target、.env提交上去了。解決辦法是先寫對(duì) .gitignore然后git rm -r --cached node_modules git commit -m 移除誤提交的目錄--cached表示只從 Git 索引中移除不動(dòng)本地文件這樣既清理了倉庫又不影響你本地繼續(xù)使用這些目錄。這套操作我在接手老項(xiàng)目時(shí)經(jīng)常用一遍就能把倉庫體積瘦下來。5. 常見報(bào)錯(cuò)與實(shí)戰(zhàn)排坑速查5.1 高頻報(bào)錯(cuò)對(duì)照表做 Git 培訓(xùn)這幾年我把團(tuán)隊(duì)成員問得最多的問題整理成了一張速查表基本能覆蓋 90% 的日常故障。報(bào)錯(cuò)信息 / 現(xiàn)象含義解決方式fatal: not a git repository (or any of the parent directories): .git當(dāng)前目錄及上級(jí)目錄都不是 Git 倉庫git init初始化或者確認(rèn)你是否 cd 錯(cuò)了目錄unable to access ... OpenSSL SSL_read: Connection was resetHTTPS 訪問遠(yuǎn)程倉庫失敗檢查網(wǎng)絡(luò)確認(rèn)遠(yuǎn)程倉庫地址是否可達(dá)fatal: refusing to merge unrelated histories兩邊倉庫歷史沒有共同祖先剛建新倉庫時(shí)用--allow-unrelated-histories合并ssh: connect to host ... port 22: Connection refusedSSH 端口不通改用 HTTPS 地址或改用 SSH 的 443 端口配置error: Your local changes would be overwritten by checkout/merge本地有未提交改動(dòng)切分支會(huì)覆蓋先 commit、stash 或記錄備份再切換fatal: Authentication failed for ...認(rèn)證失敗檢查賬號(hào)密碼是否輸對(duì)、憑據(jù)管理器是否配置、SSH 密鑰是否公鑰The following untracked working tree files would be overwritten by merge合并時(shí)被未跟蹤文件擋住把文件移走或刪除后重新合并查明是否被 .gitignore 忽略git lfs clone 卡住LFS 大文件下載慢或卡住檢查 LFS 是否安裝確認(rèn)是否有超出限額的大文件適當(dāng)?shù)却蚍峙∵@張表里的第二條值得多說一段。如果你在 clone 或 push 一個(gè)很大的倉庫時(shí)反復(fù)斷線一種有效方式是改用 SSH 協(xié)議。如果 SSH 也不穩(wěn)定還可以考慮用代理或 CDN 等方式拉取鏡像。但無論如何先確認(rèn)自己本地依賴是不是太久沒更新舊版 Git 對(duì)部分新協(xié)議支持不好也會(huì)造成莫名的連接問題。先把 Git 升級(jí)到最新穩(wěn)定版能少踩不少坑?!盁o法將‘git’項(xiàng)識(shí)別為 cmdlet”這個(gè)報(bào)錯(cuò)出現(xiàn)的原因和解決方案我在第一節(jié)講過。這里補(bǔ)充一個(gè)運(yùn)維小技巧Windows 用戶在 PATH 配置完成后可以在 CMD 里執(zhí)行where gitLinux/macOS 執(zhí)行which git如果找得到路徑說明環(huán)境沒問題IDE 找不到就是 IDE 自己的設(shè)置問題。5.2 Git 目錄安全與誤提交排查網(wǎng)絡(luò)上有一些關(guān)于“.git 目錄泄露”的討論說的是掃描網(wǎng)站文件時(shí)發(fā)現(xiàn).git目錄被公開訪問導(dǎo)致源碼歷史被扒走。這個(gè)問題的本質(zhì)是部署或發(fā)布項(xiàng)目時(shí)誤把項(xiàng)目根目錄下的.git目錄也當(dāng)作靜態(tài)文件一起暴露到了線上。作為開發(fā)者反過來要檢查的其實(shí)是自己有沒有做過“把倉庫整個(gè)傳給不該傳的人”或者“把不該提交的秘密文件傳到了遠(yuǎn)端”。正確的防御動(dòng)作有兩個(gè)。第一.gitignore一定要第一時(shí)間寫好把.env、配置密鑰、本地構(gòu)建目錄全部排除。第二提交前養(yǎng)成git status看一眼的習(xí)慣別git add .無腦全收。我見過有人把包含數(shù)據(jù)庫密碼的配置文件推到了 Gitee 上然后被爬蟲掃走這屬于安全問題屬于事故級(jí)別。處理方式是立刻改密碼而不是只刪文件因?yàn)闅v史記錄里還留著。另外還有個(gè)小技巧找歷史里的敏感信息可以用git log -p配合同步檢索工具掃描整個(gè)歷史確認(rèn)有沒有泄漏后再?zèng)Q定是否需要清理歷史。銷毀歷史是件麻煩事涉及 rewrite所以我更推薦把精力花在“別讓敏感信息進(jìn)歷史”這個(gè)環(huán)節(jié)上。5.3 我的排查思路與小技巧排查 Git 問題我有一套自己的固定流程。第一步永遠(yuǎn)是git status把當(dāng)前狀態(tài)看清楚第二步是git config --list確認(rèn)全局和本地的配置有沒有被覆蓋第三步是看本地和遠(yuǎn)程的關(guān)系用git remote -v檢查地址用git branch -vv看分支跟蹤關(guān)系第四步才是動(dòng)手操作。順手分享幾個(gè)提高效率的小配置。給常用命令配置別名會(huì)讓日常操作舒服很多git config --global alias.st status git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit git config --global alias.lg log --oneline --decorate --graph --all配置完后git lg看出的歷史圖一目了然色彩和結(jié)構(gòu)都很清楚了。還有一個(gè)我特別推薦的技巧每個(gè)倉庫提交前跑一遍git diff --check它會(huì)檢查有沒有尾隨空格、空行錯(cuò)誤這些格式問題避免無意義的 diff 噪音。團(tuán)隊(duì)協(xié)作里這種細(xì)節(jié)反而最能體現(xiàn)提交質(zhì)量。6. 寫在最后的一點(diǎn)個(gè)人經(jīng)驗(yàn)如果需要給 Git 總結(jié)一句使用心得我的個(gè)人體會(huì)是別把它當(dāng)網(wǎng)盤用。Git 的價(jià)值在于它是“有時(shí)間線的版本管理工具”核心是提交歷史干凈、可回溯、可協(xié)作。很多你遇到的問題沖突、誤提交、大文件爆炸本質(zhì)上都是沒有遵守“小而短的分支、清晰的提交信息、及時(shí)的同步”這些習(xí)慣引起的。命令本身只有那么幾個(gè)難得是把工作流養(yǎng)成肌肉記憶。最后再分享一個(gè)小技巧如果你不確定某條命令會(huì)產(chǎn)生什么后果就去一個(gè)臨時(shí)目錄里建一個(gè)空倉庫隨便創(chuàng)建幾個(gè)文件把命令在上面試一遍。這個(gè)成本幾乎為零但能讓你放心很多。Git 的容錯(cuò)率其實(shí)比想象中高只要不頻繁 force push、不隨意 reset --hard大部分錯(cuò)誤都可以用 reflog 找回來。把這些基本工作流練熟了無論是個(gè)人項(xiàng)目還是團(tuán)隊(duì)協(xié)作你都會(huì)輕松不少。