作全流程指南)
從一個(gè)小白到能正常把代碼放到GitHub上這個(gè)過程中的坑比想象中多。很多教程默認(rèn)你熟悉命令行直接甩給你一串 git 命令讓你復(fù)制粘貼結(jié)果頁面刷新后什么都沒有發(fā)生既不知道錯(cuò)在哪也不知道下一步該干嘛。這篇文章試圖換一種方式不堆砌命令列表而是把GitHub最核心的邏輯拆開講清楚再一步步帶你完成從安裝、建倉庫、提交代碼到發(fā)起 Pull Request 的完整流程順帶還會(huì)講幾個(gè)日常開發(fā)中必踩的坑。1. 先搞清楚GitHub到底在解決什么問題1.1 版本管理為什么不是多存幾個(gè)文件不少新手第一次接觸GitHub時(shí)最大的困惑是我明明可以用項(xiàng)目_最終版_v3.zip這種命名方式來管理代碼為什么要用一個(gè)看起來這么復(fù)雜的工具你可以先做一個(gè)很簡(jiǎn)單的實(shí)驗(yàn)分別在兩個(gè)文件里保存同一段代碼的不同版本然后試圖回憶起為什么第二個(gè)版本刪掉了一個(gè)函數(shù)為什么第三個(gè)版本改了變量名。這種回憶往往以失敗告終因?yàn)槟銢]有記錄改動(dòng)的原因、改動(dòng)的時(shí)間以及每處改動(dòng)的上下文。GitHub的核心價(jià)值是給整個(gè)項(xiàng)目的變化過程建立一個(gè)完整的、可追溯的記錄。它不僅保存了每個(gè)文件的最新內(nèi)容還保存了歷史中的每一次修改、誰改的、什么時(shí)候改的、改之前是什么樣、為什么改通過提交說明。這套機(jī)制的專業(yè)名稱是版本控制但你可以把它理解成一個(gè)不會(huì)丟失任何歷史痕跡的存檔點(diǎn)系統(tǒng)。1.2 本地Git和云端GitHub的分工這里還有一對(duì)經(jīng)常被混淆的概念Git 和 GitHub 不是同一個(gè)東西。Git 是一個(gè)運(yùn)行在你電腦本地的版本管理工具負(fù)責(zé)跟蹤文件變化、創(chuàng)建提交記錄、管理分支。它不依賴網(wǎng)絡(luò)也不依賴任何網(wǎng)站。你在本地做的一切操作包括 commit、branch、merge都是在自己電腦上完成的。GitHub 則是建立在 Git 之上的一個(gè)云端協(xié)作平臺(tái)。你本地的 Git 倉庫需要推送到遠(yuǎn)程端其他人才能看到、協(xié)作和同步。以一個(gè)實(shí)際項(xiàng)目為例。你在本地用 Git 初始化一個(gè)倉庫每寫一段穩(wěn)定的代碼就git commit一次形成一個(gè)存檔點(diǎn)。如果你想把這個(gè)項(xiàng)目和別人共享或者希望自己在另一臺(tái)電腦上繼續(xù)寫就需要把倉庫推送到 GitHub 上。遠(yuǎn)程倉庫的存在使多人協(xié)作成為可能——每個(gè)人在各自的本地倉庫上工作通過 push 和 pull 同步修改。很多教程一上來就讓新手安裝 Git 然后立刻開始敲命令但省略了對(duì)這套基本邏輯的鋪墊。結(jié)果就是新手在操作時(shí)根本不知道自己在和本地組件交互還是在和云端組件交互出錯(cuò)后更沒法定位問題出在哪一層。2. 新手上路第一步創(chuàng)建倉庫、克隆代碼與第一次提交2.1 前置準(zhǔn)備安裝Git與配置用戶信息工欲善其事必先利其器。不管你是哪個(gè)操作系統(tǒng)第一步都是把 Git 裝上。Windows 用戶可以從官方渠道下載安裝包安裝時(shí)建議保持默認(rèn)選項(xiàng)注意選擇能夠在右鍵菜單中使用 Git Bash這類選項(xiàng)后面操作會(huì)更順手。macOS 用戶如果裝有系統(tǒng)自帶的 command line tools通常自帶 Git不確定的話可以先在終端里輸入git --version看一眼。安裝完成后你需要做的第一件事不是創(chuàng)建倉庫而是配置身份信息git config --global user.name 你的名字 git config --global user.email 你的郵箱這段配置的用途是給每一次提交記錄打上標(biāo)簽告訴無論你還是協(xié)作者這次改動(dòng)出自誰手。如果跳過這步你第一次 commit 時(shí)大概率會(huì)看到一個(gè)提示信息告訴你需要先設(shè)置 user.name 和 user.email。這里有一個(gè)小技巧既然是全局配置建議你認(rèn)真考慮用哪個(gè)郵箱。如果打算長(zhǎng)期參與開源項(xiàng)目可以專門用一個(gè)不含太多隱私信息的郵箱或者使用平臺(tái)提供的隱私郵箱功能避免個(gè)人郵箱暴露在公開倉庫的歷史記錄里。2.2 創(chuàng)建倉庫的兩種路徑路徑一先在 GitHub 云端創(chuàng)建倉庫然后克隆到本地。登錄 GitHub 后點(diǎn)擊右上角的New repository會(huì)看到一個(gè)表單要你填倉庫名、描述、可見性public / private以及是否要自動(dòng)添加 README 文件。完成之后你會(huì)進(jìn)入一個(gè)空倉庫頁面上面顯示了幾條推薦命令。最常見的方式是復(fù)制倉庫的 HTTPS 地址然后在終端里執(zhí)行g(shù)it clone https://github.com/用戶名/倉庫名.git這條命令會(huì)把遠(yuǎn)程倉庫完整復(fù)制到當(dāng)前目錄下包含所有歷史記錄和分支。所謂克隆本質(zhì)上就是一次完整的下載。路徑二在本地先用 Git 初始化再把內(nèi)容和云端做關(guān)聯(lián)。這在你有現(xiàn)成代碼、但還沒創(chuàng)建遠(yuǎn)程倉庫時(shí)使用。操作順序是先在 GitHub 上創(chuàng)建一個(gè)空倉庫不勾選任何初始化選項(xiàng)然后回到項(xiàng)目目錄cd 你的項(xiàng)目目錄 git init git add . git commit -m first commit git remote add origin https://github.com/用戶名/倉庫名.git git push -u origin main這兩種路徑?jīng)]有本質(zhì)優(yōu)劣。如果是一個(gè)全新項(xiàng)目我其實(shí)更推薦路徑一也就是先建倉庫再克隆因?yàn)樗鼤?huì)自動(dòng)幫你處理 README、分支名等基礎(chǔ)設(shè)置減少很多新手最容易踩的分支名不一致的問題。2.3 第一次提交的完整操作假設(shè)你已經(jīng)通過克隆或初始化獲得了一個(gè)本地 Git 倉庫接下來要做的就是把文件裝進(jìn)存檔點(diǎn)。整個(gè)流程由幾個(gè)固定步驟組成查看倉庫狀態(tài)。將改動(dòng)加入暫存區(qū)。提交改動(dòng)并附上說明。推送到遠(yuǎn)程倉庫。具體命令git status git add . git commit -m 添加了項(xiàng)目初始代碼 git push對(duì)新手來說理解暫存區(qū)staging area是理解 Git 的一個(gè)關(guān)鍵點(diǎn)。你可以把暫存區(qū)想象成一個(gè)購物車。你從貨架上拿下商品修改文件后它們并不會(huì)自動(dòng)進(jìn)入購物車而是需要先git add把它們放進(jìn)去。git commit相當(dāng)于結(jié)賬明確記錄這一單買的是什么。而git push才是把這批商品從本地快遞到云端倉庫。為什么設(shè)計(jì)這個(gè)中間環(huán)節(jié)因?yàn)橛袝r(shí)候你在一個(gè)下午改了很多文件但這些文件不一定都屬于同一個(gè)邏輯單元。比如一個(gè)文件修了登錄框的 bug另一個(gè)文件加了一個(gè)新頁面你可能希望它們分成兩次提交便于以后回查歷史。如果所有改動(dòng)混作一團(tuán)直接提交以后的排查成本會(huì)很大。實(shí)際開發(fā)中我?guī)缀趺看蝕it change的文件都不止一個(gè)。合理的拆分邏輯是一次提交只做一件事。修改了接口文檔就不要夾帶私貨改了一行跟接口無關(guān)的代碼。這類習(xí)慣越是早期養(yǎng)成后面對(duì)你審視項(xiàng)目和排查問題的幫助就越大。3. 分支操作是協(xié)作的核心從本地實(shí)驗(yàn)到Pull Request全流程3.1 分支的本質(zhì)平行時(shí)空新手一開始接觸 Git 時(shí)很容易認(rèn)為所有的改動(dòng)都在一條線上依次排隊(duì)。但這個(gè)模型很快就會(huì)被團(tuán)隊(duì)協(xié)作打破——兩個(gè)人同時(shí)修改同一個(gè)文件該怎么辦答案就是分支。分支的本質(zhì)是讓一份代碼同時(shí)存在多個(gè)平行時(shí)空。在每個(gè)時(shí)空中代碼可以從同一個(gè)起點(diǎn)開始朝不同的方向演化互不干擾。完成后再把不同時(shí)空中的改動(dòng)合并回主線。以最常見的工作流為例main分支是項(xiàng)目的正式版本要求時(shí)刻處于可運(yùn)行狀態(tài)。當(dāng)你開始開發(fā)一個(gè)新功能時(shí)從main拉一個(gè)功能分支在這個(gè)分支上做實(shí)驗(yàn)。功能開發(fā)完畢后通過合并操作把改動(dòng)帶回main。這樣做的好處很明顯主線永遠(yuǎn)穩(wěn)定你的實(shí)驗(yàn)和潛在 bug 不會(huì)污染正式版本主線的維護(hù)者也有機(jī)會(huì)在合并前至少看一遍改動(dòng)。3.2 本地分支操作基礎(chǔ)從當(dāng)前分支新建并切換到一個(gè)新分支最常用的命令是git checkout -b feature/login-page這條命令等價(jià)于兩條命令的組合git branch feature/login-page創(chuàng)建分支git checkout feature/login-page切換分支。在新版 Git 中也可以使用git switch -c feature/login-page效果一致。完成開發(fā)后把當(dāng)前分支的改動(dòng)提交并推送git add . git commit -m 完成登錄頁面布局 git push -u origin feature/login-page這里的-u參數(shù)設(shè)置了一次性關(guān)聯(lián)關(guān)系告訴 Git當(dāng)前分支和遠(yuǎn)程分支建立了跟蹤關(guān)系。之后你再在這個(gè)分支上繼續(xù) push就不用每次帶上完整參數(shù)了。3.3 Pull Request不是直接合并而是發(fā)起請(qǐng)求分支合并之間有一個(gè)非常重要、也非常體現(xiàn) GitHub 價(jià)值的概念Pull Request簡(jiǎn)稱 PR在有些平臺(tái)上也叫 Merge Request。要理解 Pull Request可以先區(qū)分合并和請(qǐng)求合并這兩件事。在本地命令行里你可以直接執(zhí)行g(shù)it merge把兩個(gè)分支合并不會(huì)經(jīng)過任何審批流程。但如果是多人協(xié)作尤其是團(tuán)隊(duì)規(guī)模較大時(shí)沒有人希望誰都可以一聲不吭地把代碼改到主分支上。這時(shí) Pull Request 就登場(chǎng)了——它不是一個(gè) Git 命令而是 GitHub 提供的一種協(xié)作機(jī)制。工作流程是你在本地完成功能開發(fā)推送分支到遠(yuǎn)程倉庫。在 GitHub 網(wǎng)頁上發(fā)起 Pull Request申請(qǐng)把這個(gè)分支合并到另一個(gè)目標(biāo)分支。Pull Request 頁面會(huì)清楚展示改動(dòng)內(nèi)容——哪些文件變了、每個(gè)文件對(duì)應(yīng)哪幾行代碼被增刪。團(tuán)隊(duì)成員可以在這個(gè)頁面里逐行評(píng)論、討論。倉庫維護(hù)者審核完畢后點(diǎn)擊合并按鈕代碼才真正進(jìn)入目標(biāo)分支。相比直接合并Pull Request 的意義不只是審批流程。更重要的是它把代碼審查這個(gè)動(dòng)作沉淀成了一種可見的工作流而不是靠團(tuán)隊(duì)口頭溝通把關(guān)。對(duì)于開源項(xiàng)目來說Pull Request 還是外部貢獻(xiàn)進(jìn)入項(xiàng)目的主要入口——陌生人不能直接改動(dòng)你的倉庫但可以 fork 一份后在這個(gè)原倉庫上發(fā)起合并請(qǐng)求。有經(jīng)驗(yàn)的開源維護(hù)者審閱一份 Pull Request通常會(huì)看三件事改動(dòng)是否解決了問題描述、它會(huì)不會(huì)引入回歸、是否有遺漏的測(cè)試場(chǎng)景。你要知道的是寫清楚 PR 描述是減少協(xié)作摩擦的極高性價(jià)比操作。好的描述里至少應(yīng)該包含改動(dòng)目的、改動(dòng)內(nèi)容、測(cè)試方式、關(guān)聯(lián)的 issue 編號(hào)。我見過無數(shù)人 PR 標(biāo)題只寫fix bug或update這等于把應(yīng)該由自己承擔(dān)的上下文轉(zhuǎn)嫁給每個(gè)看 PR 的人大大降低協(xié)作效率。4. 實(shí)際協(xié)作中的高頻場(chǎng)景沖突、回滾、忽略文件的處理4.1 合并沖突不是洪水猛獸而是正常機(jī)制如果你參與過團(tuán)隊(duì)項(xiàng)目遲早會(huì)撞上合并沖突merge conflict。沖突的本質(zhì)是兩個(gè)分支修改了文件的同一行并且都認(rèn)為自己才是正確版本Git 無法自行判斷應(yīng)該保留哪個(gè)只能把決定權(quán)交給你。觸發(fā)沖突時(shí)Git 會(huì)在沖突文件里插入特殊標(biāo)記告訴你在哪個(gè)位置出現(xiàn)了分歧。打開文件后你會(huì)看到類似這樣的內(nèi)容 HEAD 這里是當(dāng)前分支的改動(dòng) 這里是對(duì)方分支的改動(dòng) feature/branch-name你需要做的就是手動(dòng)決定保留哪一邊的內(nèi)容或者融合兩者然后刪掉這些標(biāo)記行保存文件再執(zhí)行一次提交。解決沖突時(shí)我有一條幾乎不會(huì)出錯(cuò)的建議絕不只憑直覺亂改??吹?jīng)_突后先確認(rèn)這兩處改動(dòng)的意圖分別是什么。很多情況下沖突并不可怕只需要把兩邊的改動(dòng)都保留下來放在不同的位置就行——它們只是恰好出現(xiàn)在了同一行上而已。一個(gè)降低沖突頻率的實(shí)用習(xí)慣是頻繁地同步遠(yuǎn)程改動(dòng)。你 fork 一個(gè)功能分支出來前應(yīng)該先git pull一下main分支的最新內(nèi)容。開發(fā)過程中每次覺得到了一個(gè)小節(jié)點(diǎn)也建議再 pull 一次。你的分支存活時(shí)間越長(zhǎng)沖突的概率就越高。越早暴露沖突解決起來代價(jià)就越小。4.2 沒救回來的操作撤銷、回退與后悔藥開發(fā)中經(jīng)常遇到的一種慌神場(chǎng)景是提交了不該提交的東西或者發(fā)現(xiàn)自己的代碼寫錯(cuò)了想回退。Git 提供了好幾種后悔藥但每種藥的適用場(chǎng)景完全不同。如果你只是最近一次提交想改掉比如提交信息寫錯(cuò)了git commit --amend這條命令會(huì)把暫存區(qū)里新的改動(dòng)加入上一次提交同時(shí)允許你重新修改提交說明。前提是這次提交還沒有被推送到遠(yuǎn)程或者推送后還沒有被別人拉走。如果改動(dòng)已經(jīng)推送到公共分支且被人引用了用--amend就會(huì)造成歷史不一致帶來更大的麻煩。如果是想回退某次已經(jīng)推送到遠(yuǎn)程的提交用得最多的是git revertgit revert commit-idrevert的邏輯不是刪除那次提交而是創(chuàng)建一個(gè)新的提交把之前的改動(dòng)反向翻轉(zhuǎn)回來。這聽起來有點(diǎn)繞但它的好處是歷史不會(huì)被改寫等于在時(shí)間線上加了一個(gè)取消記錄。這對(duì)于協(xié)作分支來說更安全。如果你還沒有把改動(dòng)推送到遠(yuǎn)程只是想徹底抹掉最近的幾次提交git reset --hard HEAD~2這條命令會(huì)直接把 HEAD 指針退回到兩個(gè)提交之前被重置掉的那些改動(dòng)會(huì)徹底消失。注意--hard是很強(qiáng)的操作執(zhí)行后未提交的工作區(qū)改動(dòng)也會(huì)一并丟棄。我第一次實(shí)踐 reset 后就吃過一次虧把一整天的工作內(nèi)容全部沖掉了當(dāng)時(shí)心里非常崩潰。所以新手在自己不熟悉的命令前多留個(gè)心眼先用--soft或者--mixed這些溫和模式試試看或者先做一次 branch backup給自己留退路。4.3 .gitignore讓倉庫只保留該保留的東西新建項(xiàng)目時(shí)有一個(gè)文件幾乎是必需品.gitignore。這個(gè)文件的作用是告訴 Git 忽略哪些文件或目錄。在使用 Git 的過程中一開始會(huì)覺得理所當(dāng)然——所有文件都被跟蹤不是挺好嗎但很快就會(huì)出現(xiàn)下面的情況本地項(xiàng)目目錄里多了node_modules依賴包目錄、編譯輸出目錄、IDE 自動(dòng)生成的配置文件、日志文件、本地環(huán)境變量文件。如果這些都被提交到倉庫就會(huì)出現(xiàn)幾個(gè)問題。首先是大倉庫膨脹。一個(gè)node_modules目錄動(dòng)輒幾百兆每次提交、拉取都會(huì)變得很慢。其次是噪音每次增減依賴都會(huì)讓倉庫的 diff 變得不可讀卷進(jìn)大量無關(guān)文件的改動(dòng)。最后是安全風(fēng)險(xiǎn)本地環(huán)境變量文件里往往存著密鑰、口令等敏感信息。因此一個(gè)好的.gitignore至少要覆蓋下面幾類內(nèi)容依賴目錄如node_modules/編譯輸出目錄如dist/、build/系統(tǒng)文件與 IDE 配置環(huán)境變量與密鑰文件如.env、*.pem日志文件如*.logGitHub 官方對(duì)此維護(hù)了一套常用模板你可以在項(xiàng)目初始化時(shí)選擇對(duì)應(yīng)語言的標(biāo)準(zhǔn)忽略文件。但模板是通用配置實(shí)際項(xiàng)目應(yīng)根據(jù)自身情況手動(dòng)補(bǔ)充特殊情況。有一點(diǎn)要特別注意.gitignore只能對(duì)尚未被 Git 追蹤的文件生效。如果你之前已經(jīng)把某個(gè)文件提交過了再在.gitignore里加一行忽略規(guī)則Git 并不會(huì)停止追蹤它的變化。這時(shí)候需要用git rm --cached 文件名先把文件從追蹤列表中移除再配合忽略規(guī)則才有效果。5. HTTPS還是SSH連接認(rèn)證方式的選擇5.1 Token認(rèn)證現(xiàn)代GitHub推薦的方式把代碼推送到 GitHub 需要身份驗(yàn)證。早些年這個(gè)環(huán)節(jié)最簡(jiǎn)單的方式是輸密碼但出于安全考慮GitHub 很早就取消了賬戶密碼直接用于 Git 操作的方式取而代之的是個(gè)人訪問令牌Personal Access Token簡(jiǎn)稱 PAT。這個(gè)令牌相當(dāng)于一張限權(quán)門禁卡可以設(shè)定權(quán)限范圍和有效期限。創(chuàng)建方式很直接在 GitHub 設(shè)置頁面中選擇生成新令牌勾選需要的權(quán)限范圍至少需要repo權(quán)限才能對(duì)代碼倉庫進(jìn)行推送生成后復(fù)制并保存好這段字符串。它只會(huì)在生成的那一刻完整顯示一次之后你無法再查看原值只能重新生成。拿到 Token 后HTTPS 協(xié)議下的 push 操作會(huì)自動(dòng)提示你輸入用戶名和密碼。用戶名填你的 GitHub 用戶名密碼處不要填密碼粘貼 Token 進(jìn)去即可。為了防止每次操作都輸入一次你還可以配置系統(tǒng)憑證管理器讓系統(tǒng)記住這部分憑據(jù)后續(xù)自動(dòng)攜帶。使用 Token 的最大優(yōu)勢(shì)是權(quán)限精細(xì)可控。即使某個(gè) Token 不幸泄露你可以在設(shè)置頁面直接吊銷它而不需要改動(dòng)任何其他東西。5.2 SSH Key免密的長(zhǎng)期選擇如果你需要在多臺(tái)設(shè)備上頻繁操作倉庫SSH 方式是體驗(yàn)更好的選擇。SSH 的認(rèn)證思路是我認(rèn)鑰匙不認(rèn)人。你在本地生成一對(duì)密鑰——一把私鑰自己留好、一把公鑰放置到 GitHub 賬號(hào)設(shè)置里。之后本地 Git 向 GitHub 發(fā)起連接時(shí)GitHub 通過密鑰匹配完成身份確認(rèn)不再需要每次輸入賬號(hào)和 Token。生成過程ssh-keygen -t ed25519 -C 你的郵箱一路回車即可生成默認(rèn)位置的一對(duì)密鑰。然后查看公鑰內(nèi)容cat ~/.ssh/id_ed25519.pub復(fù)制輸出的一大段字符串粘貼到 GitHub 設(shè)置里的SSH and GPG keys頁面即可。之后把倉庫的遠(yuǎn)程地址改成 SSH 形式即可。事項(xiàng)HTTPSSSH首次配置需要生成 Token需要生成密鑰對(duì)后續(xù) push憑據(jù)管理后可記住免密安全粒度可單獨(dú)吊銷 Token私鑰泄露需重新生成適合場(chǎng)景臨時(shí)設(shè)備、共享設(shè)備個(gè)人長(zhǎng)期設(shè)備對(duì)新手我的建議是如果只是偶爾使用或使用場(chǎng)景在公共電腦上選擇 HTTPS Token 更省心。如果是自己日常使用的固定設(shè)備值得花幾分鐘配好 SSH后面每次 push 都節(jié)省幾秒操作。不要兩種混著用選擇一個(gè)認(rèn)定后保持專注避免把遠(yuǎn)程地址反復(fù)改來改去造成多余的心理負(fù)擔(dān)。5.3 常用命令一覽與查詢技巧很多新手遇到的實(shí)際問題是命令一多就亂套。其實(shí)日常開發(fā)需要熟練敲入的命令不超過二十條。這里我做了一份高頻命令清單可以當(dāng)成速查卡# 查看倉庫狀態(tài)推薦頻繁執(zhí)行 git status # 查看提交歷史 git log --oneline # 把改動(dòng)放進(jìn)暫存區(qū) git add 文件名 # 提交改動(dòng) git commit -m 說明信息 # 推送本地提交到遠(yuǎn)程 git push # 拉取遠(yuǎn)程最新改動(dòng) git pull # 新建并切換分支 git checkout -b 分支名 # 切換分支 git checkout 分支名 # 合并分支到當(dāng)前分支 git merge 分支名比忘命令更讓人沮喪的是忘了一堆參數(shù)的含義。我的經(jīng)驗(yàn)是不需要把所有命令都背下來Git 的幫助系統(tǒng)就是最好的記憶輔助遇到想不起來的參數(shù)用git help 命令名或者git 命令名 --help調(diào)出完整說明文檔即可。6. 新手起步階段最容易忽略的操作習(xí)慣6.1 提交信息要寫得像一封短備忘錄而不是一堆隨機(jī)字符如果你去翻一些知名開源項(xiàng)目的提交歷史會(huì)發(fā)現(xiàn)一個(gè)普遍規(guī)律幾乎每條提交信息都在回答兩個(gè)問題——這次改了什么和為什么這么改。相比之下新手常見的提交信息是這樣的update、add files、fix、coding、修改。假設(shè)三個(gè)月后你再也想不起來自己在做什么拉到一條fix你會(huì)獲得多少線索幾乎沒有。這里分享一個(gè)簡(jiǎn)單好上手的提交信息模板類型(范圍): 簡(jiǎn)短描述 詳細(xì)說明可選類型通常有 fix修 bug、feat新功能、docs文檔改動(dòng)、refactor重構(gòu)、style格式調(diào)整等。范圍指這次改動(dòng)影響到的模塊。描述則用一句話說清楚核心內(nèi)容比如fix(auth): 修復(fù)登錄后token未刷新導(dǎo)致接口401。我不是說必需嚴(yán)格按某個(gè)規(guī)范書寫。關(guān)鍵是讓描述帶有足夠上下文別人接手時(shí)不需要重新閱讀全量 diff 也能大概理解這次的改動(dòng)目標(biāo)。這個(gè)習(xí)慣帶來的長(zhǎng)期收益遠(yuǎn)比看起來大得多——你最終讀歷史記錄的時(shí)間和寫代碼的時(shí)間可能是等量齊觀的。6.2 什么時(shí)候該提交什么時(shí)候不該提交新手還有兩個(gè)相鄰的困惑一是改動(dòng)多大才值得提交二是代碼沒寫完要不要提交。先說不值得提交的類型。幾百個(gè)文件里有一半是系統(tǒng)自動(dòng)生成的臨時(shí)文件不該進(jìn)提交。代碼里有調(diào)試用的臨時(shí)打印、試運(yùn)行后的廢棄函數(shù)也不建議提交。再說說提交節(jié)奏。經(jīng)驗(yàn)法則是只要當(dāng)前狀態(tài)下代碼可以正常結(jié)束、不會(huì)有編譯錯(cuò)誤且你清楚這次提交的目標(biāo)就值得提交。提交得越頻繁歷史里能表達(dá)的信息就越多未來定位問題的切分點(diǎn)也越細(xì)。大量不成為提交沒有價(jià)值也沒有意義。有一種做法強(qiáng)烈不推薦一口氣寫了幾千行然后一次性提交。這會(huì)讓代碼審查幾乎不可行——沒人能在一頁幾百個(gè)文件里注意到局部的小問題。正確姿勢(shì)是每完成一個(gè)小功能點(diǎn)即提交一次盡量讓每次提交足夠原子化。6.3 README與License讓倉庫從代碼片段變成完整項(xiàng)目一個(gè)完整的 GitHub 倉庫代碼以外通常還有兩個(gè)標(biāo)配文件。README 是用來承載項(xiàng)目說明的入口文件。它的核心內(nèi)容通常包括這個(gè)項(xiàng)目解決了什么問題、環(huán)境要求、如何安裝、如何調(diào)用、如何測(cè)試。對(duì)開源項(xiàng)目而言優(yōu)秀的 README 還能起到說明書營銷頁的作用讓訪問者一眼就知道這個(gè)倉庫值得不值得點(diǎn) star 或者提交 issue。License 則決定了別人能不能合法地使用、修改、分發(fā)你的代碼。很多人以為只要我把代碼公開在 GitHub 上別人就默認(rèn)可以用這是一個(gè)常見誤解。從版權(quán)角度說公開代碼不代表放棄版權(quán)。如果倉庫里沒有 License那么法律意義上其他人仍然不能隨意使用你的代碼來做商業(yè)項(xiàng)目等。GitHub 有標(biāo)準(zhǔn)化的選許可證流程如果你不關(guān)心細(xì)節(jié)MIT License是自由度較高且最常見的選擇之一。7. 從入門到日常使用一些過來人的體會(huì)寫到這里基礎(chǔ)的 Git 操作和 GitHub 業(yè)務(wù)流程其實(shí)已經(jīng)串起來了。最后再分享幾條我踩過不少坑之后覺得比學(xué)會(huì)命令更重要的心得。第一先學(xué)會(huì)看報(bào)錯(cuò)信息。新手遇到 push 失敗時(shí)經(jīng)常會(huì)慌把一大段紅色報(bào)錯(cuò)粘貼到搜索引擎里然后照著別人給的命令亂七八糟敲。但實(shí)際上多數(shù)報(bào)錯(cuò)信息本身已經(jīng)把問題說得很清楚了。最典型的比如failed to push some refs通常在報(bào)錯(cuò)提示上方就已經(jīng)解釋了原因——遠(yuǎn)端有本機(jī)沒有提交的數(shù)據(jù)。這時(shí)候執(zhí)行g(shù)it pull同步一次通常問題就解決了。第二養(yǎng)成git status和git log的好習(xí)慣。它們不單單能告訴你倉庫當(dāng)前狀態(tài)還能幫你觀察我當(dāng)前到底在哪個(gè)分支我的上一次提交到底是什么。尤其在操作了幾個(gè)倉庫之后大腦很容易記混不同項(xiàng)目的分支狀態(tài)而命令給出的信息是最可信的。第三不要畏懼沖突和你確認(rèn)不了的操作。Git 設(shè)計(jì)得非常嚴(yán)密的一點(diǎn)在于幾乎每個(gè)危險(xiǎn)操作都留了至少一條退路。只要你的代碼推送到遠(yuǎn)端或者有了備份副本本地即使全部擼掉也可以搶救回來。我本人的經(jīng)歷是手滑執(zhí)行過 reset、誤刪過分支也在別人的主導(dǎo)下被迫解決過一次跨文件的沖突。遇到這類情況時(shí)最重要的反而是耐心——逐個(gè)文件、逐行信息確認(rèn)而不是靠直覺和運(yùn)氣。如今打開任何成熟的軟件項(xiàng)目主頁第一眼看到的都是 README、分支、貢獻(xiàn)指南、Pull Request 流程等信息。這套基礎(chǔ)設(shè)施相當(dāng)深入人心。作為入門者花幾個(gè)小時(shí)搞懂背后的原理遠(yuǎn)比你背下二十個(gè)命令更有長(zhǎng)期價(jià)值。上手之后你會(huì)發(fā)現(xiàn)GitHub 非但不復(fù)雜反而是那種越用越順手、一旦用慣了再也不想回到文件命名管理法的工具。我很認(rèn)真地希望你邊讀邊打開電腦試試而不是收藏完就放在那里。畢竟 Git 類的工具讀再多的經(jīng)驗(yàn)文章也不如親手推送一次來得直觀。