我的日常工作和開源工作經常要用到 git 和 GitHub ,所以我發現了有一些我經常用到的實用模式。
下文中我會把 pull 請求(pull request)簡寫成PR。
1. 剝離的PR
我什麼時候用?
- 工作在特性開發分支
- 發現不好的程式碼想要馬上就地修正,但是和我正在做的特性無關(例如一個小bug,或者哪裡不一致,或者有違背程式碼規範)
我該做什麼?
- 暫停當前的進度(通過提交commit或者暫存stash)
- 檢出master分支
- 新建分支
- 修正程式碼,提交
- 切換回特性開發分支,繼續工作
- 等特性開發分支合併(merge)到master分支後,再變基(rebase)到前面新建的分支上
這個既滿足想要快速修正無關問題的願望,又能保持特徵開發分支的清晰明瞭,讓評審變得更容易。
2. 樂觀的分支
我什麼時候用?
- 有一個暫不能合併(例如持續整合構建失敗,程式碼評審者很忙等原因)的分支(分支A)
- 我需要基於分支A的程式碼做另一個改動
我該做什麼?
- 在分支A上建立一個新的分支(分支B)
- 等分支A合併到master分支後,把分支B變基到master分支,並解決產生的任何衝突
- 這樣在分支A上對bug的修正都變基到分支B上了
這種處理有衝突的風險,如果在分支A上做的改動特別大。但是這個樂觀的策略95%的情況都工作良好。
3. 機智的PR
我什麼時候用?
- 假設我做的修改事實上不需要評審
- 我還是需要我的隊友知道這件事
我該做什麼?
- 在分支上做修改
- 報一個PR
- 自己迅速合併這個PR
這個方法不會阻礙我的繼續,但是GitHub還是會通過郵件通知我的隊友這個PR。因此大家覺得有異議也都可以評論這個修改。
4. 偷偷摸摸的提交
我什麼時候用?
- 程式碼評審過了,並且合併到了master
- 我需要做一個小改動(例如複製改動,或者bug修正),但是沒必要通知別人
我該做什麼?
- 只要把新的提交push到master
5. the roger roger 評論
我什麼時候用?
- 從分支的程式碼評審那裡收到了可操作的回饋
- 已經基於回饋做好了相應的修改
我該做什麼?
* 評論包含了該修改提交的引用的PR
* GitHub會聰明地在差異連結處增加引用的次數,這樣我的同事:
→ 得到修改的郵件通知
→ 簡單地點選提交差異連結
→ 知道他們可以繼續程式碼評審了
6. 慢慢爬的提交
我什麼時候用?
- 發現自己引入了一個小小的格式化的bug(例如不必要的空格,檔案最後沒有換行等),或者
- 某邏輯程式碼修改實際上屬於前一個提交, 或者
- 程式碼不可提交(例如某些測試未成功)但是我還是想要回退到這個狀態,這樣我可以安全地測試
我該怎麼做?
- 前兩種情況,我會補救amend前一次提交
- 第三種情況,我有一個正在開發的(爬行的)提交,我漸進地進行補救(或者如果實驗失敗那就回退)直到我的程式碼可以真正提交了。
7. 強制修改的分支
我什麼時候用?
- 我需要補救一個遠端功能開發分支,例如提交資訊裡的說明非常糟糕
我該做什麼?
- 在本地補救提交
- 把該功能開發分支強制推送到遠端的版本庫
強制推送到遠端分支應該是 git 的一個禁忌,但是我的經驗是這樣處理很少有問題(只要它是普通分支,不是master就行)。GitHub 能很好地處理強制推送到PR分支,例如不會丟失前一次的提交的評論。
8. 重新格式化剝離
我什麼時候用?
- 我想修改同時格式化程式碼
我該做什麼?
- 在master上做一個僅包含重新格式化部分的提交
- 把我分支變基到master
這種方法,讓分支的差異在程式碼評審者眼裡變得更加清晰明瞭,因為它不包含格式化
9. 原型PR
我什麼時候用?
- 想要讓我的點子在寫大量實現程式碼前得到大家的反饋
我該做什麼?
- 在某個分支上做點整理
- 為此報一個PR,目的不是要釋出最終程式碼,而是作為大家討論的出發點
- 當達成一致開始下一步時關閉該PR(並且刪除分支)
- 新建另外一個分支和PR,這次好好寫程式碼
我以前習慣於當程式碼完成時應該報一個PR。現在我真正領悟到了為什麼“pull request是一個開始討論的好辦法” —— GitHub的圍繞PR的功能(例如內聯評論、回覆、通知和比較差異)對於促進程式碼和設計討論堪稱卓越,還可以防止開發者偏離正題太遠,跑到死衚衕。