帶新人第一週,他一個 force push 蓋掉了整個下午的 commit——我的 Git 工作流反思
消失的一個下午
帶新人的第一週,出事了。
那天下午團隊三個人都在同一個功能分支上推東西。新人在本地 rebase 完,遇到衝突,慌了,於是他做了那件所有人都叫你不要做的事:git push --force。他把遠端分支硬推成他本地的版本,另外兩個人整個下午的 commit,就這樣從遠端消失了。
還好 Git 幾乎不會真的刪東西,我們靠 reflog 跟本地還留著的 commit 把東西撿了回來,折騰一個多小時。但那件事讓我認真想了一件事:這不是新人的錯,是我的流程沒有保護好他。一個第一週的人,本來就不該有能力對著共用分支 force push。這篇講我從個人到帶團隊,Git 工作流是怎麼一路調整的,核心其實只有一句:流程是為了讓犯錯的代價變小。
一個人的時候:簡單,但留紀錄
自己一個專案,我不搞複雜的分支模型,就是主線開發。但有兩個習慣我從很早就養成:
- commit 訊息好好寫,講清楚「為什麼改」,而不是「改了什麼」。程式碼本身就能看出改了什麼,看不出的是你當時的考量。
- 就算一個人,功能大一點也開分支做,做完再合回主線。這讓主線隨時是能動的狀態。
這些習慣在只有自己的時候看起來多餘,但它們是你之後進團隊的地基。
團隊協作:分支策略要配合節奏
進了團隊,分支策略沒有標準答案,要配合你們出版本的節奏。
我待過的團隊,簡單的就用「主線 + 功能分支」,每個功能開一條分支,做完發 PR 合回去。發版節奏比較重、需要同時維護正式版跟開發版的,才會用到多一條 release 分支。重點不是抄哪個知名的分支模型,是選一個跟你們實際發版方式對得上的,別為了流程而流程。
那次 force push 事件之後,我做的第一個改變是:主線跟共用分支加上保護規則,禁止 force push、必須經過 PR 才能合併。把危險的操作從「靠大家自律」變成「系統根本不讓你做」。
Pull Request 是溝通,不只是合併
我越來越把 PR 當成一個溝通的場合,而不只是「把程式碼合進去的按鈕」。
一個好的 PR 描述,會講清楚這次改動想解決什麼、為什麼這樣做、有沒有什麼取捨或風險。review 的人看的不只是程式碼對不對,還有這個改動合不合理。我帶人之後特別強調這個——因為 PR 的描述跟討論,會變成半年後某個人來追這段程式碼「為什麼長這樣」時,唯一的線索。
commit 歷史是寫給未來的人看的
那個未來的人,很多時候就是半年後的你自己。
我在追一個詭異 bug 的時候,最常做的事就是用 git blame 看某一行是什麼時候、為了什麼被改成這樣。這時候如果那條 commit 訊息只寫了「fix bug」「update」,我會很想穿越回去揍當時的人。反過來,一條講清楚來龍去脈的 commit,可以幫我省下半小時的猜測。所以整理 commit、讓歷史清楚可讀,不是潔癖,是在幫未來的人(包括你)省時間。
帶人之後最大的體會:流程是為了降低恐懼
繞了一圈,我對 Git 工作流最深的體會,是那次 force push 給的:流程的目的,是讓人敢動手,而不是讓人綁手綁腳。
一個好的流程,會讓新人知道「就算我搞砸了,也有 PR review 擋著、有分支保護擋著、有歷史可以復原」,於是他敢去改、敢去嘗試。一個爛的流程,要嘛限制太多讓人動彈不得,要嘛毫無防護讓一次失誤就釀成災難——像我當初那樣。
所以現在我設計團隊的 Git 流程,判斷標準只有一個:它有沒有讓「犯錯」這件事變得安全。安全了,人才敢跑。
小結
Git 的指令你查文件都有,分支模型網路上一堆圖。但那些都是表面。那次消失的一個下午教我的是,工作流的本質不是規範,是保護——保護每個人的成果不會被一次失誤抹掉,保護新人敢在一個有安全網的環境裡犯錯、成長。技術是死的,讓團隊敢動手的那層安全感,才是你真正要設計的東西。
留言討論
有想法、有不同經驗、或想糾正我?歡迎在下面留言,免註冊,填個暱稱就能留。