拉取請求
2021 年 1 月 28 日
拉取請求是 github 推廣的一種機制,用於協助合併工作,特別是在開源專案的背景下。貢獻者在中心儲存庫的分支(複製)中處理他們的貢獻。一旦完成他們的貢獻,他們就會建立一個拉取請求,通知中心儲存庫的所有者,表示他們的成果已準備好合併到主線中。工具支援並鼓勵在接受請求之前對貢獻進行程式碼檢閱。拉取請求已在軟體開發中廣泛使用,但批評者擔心會增加整合摩擦,進而阻礙持續整合。
拉取請求基本上為許多開源專案中存在的開發工作流程提供便利的工具,特別是那些使用分散式原始碼控制系統(例如 git)的專案。此工作流程從貢獻者建立新的邏輯分支開始,方法是從中心儲存庫開始新的分支、複製到個人儲存庫,或同時進行。然後貢獻者在該分支上工作,通常採用 功能分支 的樣式,將 主線 的任何更新拉取到他們的分支中。完成後,他們會與中心儲存庫的維護者溝通,表示他們已完成,並附上他們提交的參考。此參考可能是需要整合的分支網址,或電子郵件中的一組修補程式。
維護者收到訊息後,可以檢查提交,以決定是否準備好放入主線。如果不是,她可以建議貢獻者進行變更,然後貢獻者就有機會調整他們的提交。一旦一切正常,維護者就可以合併,使用一般的合併/變基,或套用最後電子郵件中的修補程式。
Github 的拉取請求機制讓這個流程變得容易許多。它透過分叉機制追蹤複製,並自動建立訊息串討論拉取請求,以及處理檢閱工作流程中各個步驟的行為。這些便利性是讓 github 成功的主要因素,也讓「拉取請求」成為開發人員詞彙中的基本部分。
這就是拉取請求的工作方式,但我們應該使用它們嗎?如果是,該如何使用?為了回答這個問題,我喜歡跳脫機制,思考它在原始碼管理工作流程中的運作方式。為了幫助我思考這個問題,我寫下了一系列 管理原始碼分支的模式。我發現了解這些模式(特別是基礎和整合模式)能釐清拉取請求的角色。
就這些模式而言,拉取請求是一種機制,旨在實作 功能分支 和 整合前檢閱 的組合。因此,若要評估拉取請求的效用,我們首先需要考量這些模式與我們情況的適用性。如同大多數模式,它們有時很有價值,有時卻很討厭 - 我們必須根據特定脈絡來檢視它們。功能分支是一種將邏輯貢獻打包在一起的良好方式,以便將其評估、接受或遞延為單一單元。當不信任貢獻者直接提交到主線時,這很有意義。但是,功能分支是有代價的,通常會限制整合頻率,導致複雜的合併並阻礙重構。整合前檢閱提供了一個明確的位置來進行程式碼檢閱,但代價是整合摩擦顯著增加。[1]
這是對情況的徹底總結(我需要更多文字才能在功能分支文章中進一步說明這一點),但歸根結底,這些模式的價值,以及拉取請求的價值,主要取決於團隊的社會結構。有些團隊使用拉取請求可以發揮更好的效果,有些團隊則會發現拉取請求嚴重拖累效率。我懷疑由於拉取請求如此受歡迎,許多團隊在沒有拉取請求的情況下會做得更好,卻預設使用拉取請求。
雖然拉取請求是為功能分支而建構的,但團隊可以在 持續整合 環境中使用它們。為此,他們需要確保拉取請求足夠小,而且團隊反應靈敏,以遵循 CI 的經驗法則,即每個人都至少每天進行 主線整合。(我應該提醒大家,主線整合不僅僅是將目前的主線合併到功能分支中)。使用 發布/展示/詢問 分類可以是將拉取請求整合到更友善 CI 的工作流程的有效方式。
廣泛使用拉取請求已鼓勵更廣泛地使用程式碼檢閱,因為拉取請求提供了明確的整合前檢閱點,並搭配鼓勵使用的工具。程式碼檢閱是一件好事,但我們必須記住,拉取請求並非我們能使用的唯一機制。許多團隊在配對程式設計提供的「持續檢閱」中發現了極大的價值。為避免降低整合頻率,我們可以透過多種方式執行整合後程式碼檢閱。正式流程可以為每個提交記錄檢閱,或技術主管每隔幾天檢查一次有風險的提交。也許最有效的程式碼檢閱形式之一就是經常被忽略的。一個採取程式碼庫是流動系統的態度,一個可以透過重複迭代穩步改善的團隊,每次開發人員查看現有程式碼時都會執行「改善程式碼檢閱」。我經常聽到人們說拉取請求是必要的,因為沒有拉取請求就無法進行程式碼檢閱——這簡直是無稽之談。整合前程式碼檢閱只是執行程式碼檢閱的一種方式,對於許多團隊而言,這並非最佳選擇。
致謝
Chris Ford、Dan Mutton、Jeremy Huiskamp、Kief Morris、Pramod Sadalage 和 Ryan Boucher 在我們的內部郵件清單上對這篇文章的草稿發表了評論。註解
1: 我的一位同事最近計算了一位客戶等待沒有評論的拉取請求所花費的時間(91% 的拉取請求都是如此)。2020 年等待 7000 個拉取請求的總時間為 130,000 小時。此數字包括晚上和週末經過的時間。