譯者 | 劉汪洋
審校 | 重樓
概括:這篇文章介紹了 Merge Queue 這一新的代碼合并方式,它可以讓開發(fā)者不用擔(dān)心代碼沖突和等待時(shí)間,而是把合并的任務(wù)交給一個(gè)自動(dòng)化的隊(duì)列來(lái)處理。文章還介紹了一個(gè)實(shí)現(xiàn)了 Merge Queue 的工具 Mergify,它可以與 GitHub 集成,讓開發(fā)者更方便地使用 Merge Queue。
盡管幾個(gè)月前“合并隊(duì)列”還是一個(gè)不太為人所知的術(shù)語(yǔ),現(xiàn)在卻越來(lái)越受到業(yè)界的重視。無(wú)論是像 GitHub 這樣的行業(yè)領(lǐng)袖的公告,還是實(shí)際的技術(shù)解決方案,合并隊(duì)列正逐漸被軟件開發(fā)團(tuán)隊(duì)所采納。
因此,你可以深入探討這一主題,了解合并隊(duì)列的定義,其適用場(chǎng)景,以及它們?cè)趯?shí)際操作中的工作原理。
準(zhǔn)備好了嗎?讓我們開始吧。
“合并隊(duì)列”是什么?
在探討為何要使用合并隊(duì)列之前,我們首先需要明確它的定義。
顧名思義,合并隊(duì)列是一系列等待合并的 Pull Request (簡(jiǎn)稱 PR)的排列順序。
每位團(tuán)隊(duì)成員每天都可能創(chuàng)建許多 Pull Request,然后由倉(cāng)庫(kù)維護(hù)者將其加入隊(duì)列。聽起來(lái)很簡(jiǎn)單,不是嗎?
更準(zhǔn)確地說,你不僅僅是將基礎(chǔ)的 PR 加入隊(duì)列。隊(duì)列中的所有 PR 都已經(jīng)得到了維護(hù)者的批準(zhǔn),這意味著它們已經(jīng)通過了所有必要的檢查。
因此,你得到了一個(gè)充滿已驗(yàn)證 Pull Request 的隊(duì)列。這聽起來(lái)很有趣,但似乎并不實(shí)用。為什么不逐一合并它們呢?為了解答這個(gè)問題,我們先來(lái)看看如果你不使用合并隊(duì)列,可能會(huì)遇到哪些常見問題。
為什么需要合并隊(duì)列?
坦白說,有許多理由支持使用合并隊(duì)列。在這一部分,你將了解一個(gè)真正棘手的問題,以及如何通過使用合并隊(duì)列來(lái)解決它。
常見問題:合并過時(shí)的 Pull Request
要理解合并隊(duì)列如何解決問題,你首先必須了解問題本身。
請(qǐng)想象以下場(chǎng)景:
- 主分支已經(jīng)通過了持續(xù)集成測(cè)試。
- 創(chuàng)建了一個(gè) Pull Request,并通過了 持續(xù)集成(CI),我們稱之為 PR1。
此時(shí),你可以通過以下圖示來(lái)表示倉(cāng)庫(kù)的狀態(tài):
image.png
目前一切似乎都在正常運(yùn)行,但這種情況并不會(huì)持續(xù)下去。讓我們深入了解一下。
當(dāng) PR1 仍處于打開狀態(tài)時(shí),主分支接收了另一個(gè)提交。無(wú)論這個(gè)新提交是直接推送到主分支還是從另一個(gè) Pull Request 合并的,關(guān)鍵是主分支已經(jīng)發(fā)生了變化。
隨后,持續(xù)集成(CI)系統(tǒng)針對(duì)主分支運(yùn)行了測(cè)試,并再次通過。此時(shí),你可以通過以下圖示來(lái)描述你的倉(cāng)庫(kù)及其持續(xù)集成系統(tǒng)的狀態(tài):
image.png
你會(huì)注意到 PR1 仍被持續(xù)集成系統(tǒng)視為有效,這是合理的,因?yàn)橹挥兄鞣种Оl(fā)生了變化,而 PR1 并未發(fā)生改變。
由于代碼之間沒有沖突,GitHub 認(rèn)為 PR1 是可以合并的,合并按鈕變成了綠色。
你滿懷信心地點(diǎn)擊了那個(gè)綠色按鈕。
然而,正如你所預(yù)料,這可能會(huì)帶來(lái)一個(gè)意外的“驚喜”——并不是好事。
現(xiàn)在,當(dāng)你試圖合并 PR1 并創(chuàng)建了一個(gè)新的合并提交時(shí),持續(xù)集成測(cè)試卻失敗了。為什么會(huì)這樣呢?
image.png
實(shí)際上,當(dāng) PR1 被標(biāo)記為有效時(shí),CI 并沒有用主分支新添加的提交再次測(cè)試 PR1。
然而,主分支中的最后一個(gè)提交引入了新的測(cè)試,而 PR1 并未包含正確的代碼來(lái)通過這個(gè)新測(cè)試,這一情況雖讓人沮喪,但卻合情合理。
如何應(yīng)對(duì)這一挑戰(zhàn)?
這個(gè)問題的核心在于 Rebase 的操作以及每個(gè) Pull Request 需要與主分支保持最新的必要性。如果你不采用合并隊(duì)列,通常有兩個(gè)選擇:
- 僅在功能分支的頂部運(yùn)行持續(xù)集成,不強(qiáng)制功能分支與主分支保持同步。主要缺點(diǎn)是功能分支可能與主分支兼容,但也可能不兼容。
- 要求所有功能分支與目標(biāo)分支保持最新。主要缺點(diǎn)在于這會(huì)消耗大量的時(shí)間和資源。
對(duì)于采用持續(xù)集成/持續(xù)交付(CI/CD)流程的組織和團(tuán)隊(duì)來(lái)說,這是一種常見的挑戰(zhàn)。如果你正面臨這個(gè)問題,不必?fù)?dān)心,因?yàn)檎嬲慕鉀Q方案已經(jīng)找到了!
真正的解決方案:合并隊(duì)列
解決方案就是使用合并隊(duì)列。它在合并之前會(huì)更新所有與主分支不同步的 Pull Request。實(shí)際上,合并隊(duì)列會(huì)要求 CI 系統(tǒng)使用主分支的最新代碼重新測(cè)試 PR。
如果你在之前描述的情況下使用合并隊(duì)列,系統(tǒng)會(huì)自動(dòng)將主分支合并到功能分支中。
如下圖所示,CI 將重新運(yùn)行測(cè)試。如果 Pull Request 失敗,則會(huì)被標(biāo)記為失敗并從隊(duì)列中移除。當(dāng)然,如果 PR 有效,并且所有檢查都通過了,它將被合并。
image.png
另一個(gè)實(shí)際場(chǎng)景:多個(gè) Pull Request 已驗(yàn)證,準(zhǔn)備合并。
合并隊(duì)列會(huì)按照順序安排這些 Pull Request 的合并,并確保它們與主分支保持同步。當(dāng)然,只有當(dāng) Pull Request滿足所有條件時(shí),才會(huì)進(jìn)行同步更新。
但是,如果你剛合并了一個(gè)已更新的 Pull Request,緊接著又發(fā)現(xiàn)另一個(gè) Pull Request 仍然過時(shí),那會(huì)發(fā)生什么情況呢?為了更清晰地解釋這個(gè)過程,我們可以通過下圖來(lái)理解:
image.png
合并隊(duì)列的作用是確保在合并之前,第二個(gè) Pull Request 與主分支的最新版本保持同步。通過這樣的操作,可以避免將過時(shí)或有缺陷的 Pull Request 合并到主分支中。
image.png
你可以根據(jù)需要重復(fù)這個(gè)過程,逐一處理隊(duì)列中的每個(gè)過時(shí) Pull Request。
雖然軟件開發(fā)的過程并不總是簡(jiǎn)單,但合并隊(duì)列的使用無(wú)疑可以讓整個(gè)流程變得更加順暢和高效。
合并隊(duì)列的工作機(jī)制
了解合并隊(duì)列能解決的問題后,我們來(lái)深入探討其工作機(jī)制。
合并隊(duì)列在視覺上可能顯得有些復(fù)雜,我們可以逐步分析其工作流程和組成部分。
1. 將有效的 PR 加入隊(duì)列
合并隊(duì)列引擎會(huì)在你的 Pull Request 上運(yùn)行。所有滿足條件的 Pull Request 將被添加到隊(duì)列中。
2. 更新與 CI
合并隊(duì)列會(huì)確保隊(duì)列中的每個(gè) PR 與主分支保持同步,以確保其最新狀態(tài)。
隨后,CI 會(huì)重新運(yùn)行,以確認(rèn) PR 是否可以合并。
3. 合并還是不合并:決策點(diǎn)
存在兩種截然不同的情況:
- 所有檢查通過 → 合并 PR。
- 測(cè)試失敗 → 將 PR 從隊(duì)列中移除。
Mergify 的合并隊(duì)列特點(diǎn)是什么?
具體來(lái)說,Mergify 的合并隊(duì)列實(shí)現(xiàn)了你剛剛了解的所有功能。
作為市場(chǎng)上首批合并隊(duì)列之一,Mergify 已經(jīng)贏得了數(shù)千名用戶的滿意評(píng)價(jià)。
雖然前述的常見功能足以解決許多棘手問題,但在更復(fù)雜和特定的情況下,你可能需要一些非常具體的功能。
幸運(yùn)的是,Mergify 可以滿足這些需求!
1. 推測(cè)性檢查:并行測(cè)試不同的 PR
隊(duì)列中的第一個(gè) Pull Request 將被加入合并流程,并與其他請(qǐng)求一起并行測(cè)試,以便更快地合并。
image.png
2. 批次處理:一次檢查和合并多個(gè) PR
Mergify 通過 batch_size 選項(xiàng)允許一次性檢查多個(gè) Pull Request 的合并性。
3. 多隊(duì)列管理:將 PR 分配到專用隊(duì)列
通過使用多個(gè)隊(duì)列,可以根據(jù)優(yōu)先級(jí)將 Pull Request 分配到不同的隊(duì)列中。
4. 隊(duì)列凍結(jié):暫停所有合并過程
Mergify 允許暫停一個(gè)或多個(gè)隊(duì)列的合并過程,從而增強(qiáng)了對(duì)代碼合并方式、時(shí)間的控制和靈活性。
5.優(yōu)先級(jí)管理:優(yōu)先處理特定 Pull Request
你可以根據(jù)標(biāo)簽、所有者等因素選擇哪個(gè) PR 應(yīng)該首先合并。最終的決策權(quán)在你手中!
結(jié)論
現(xiàn)在,各位讀者應(yīng)該對(duì)合并隊(duì)列的概念有了全面的了解,從工作原理到使用的理由,這一概念對(duì)你來(lái)說應(yīng)該已經(jīng)一目了然。如果你想使用 Mergify 的合并隊(duì)列解決方案,可以去官網(wǎng)進(jìn)一步詳情。
譯者介紹
劉汪洋,51CTO社區(qū)編輯,昵稱:明明如月,一個(gè)擁有 5 年開發(fā)經(jīng)驗(yàn)的某大廠高級(jí) Java 工程師,擁有多個(gè)主流技術(shù)博客平臺(tái)博客專家稱號(hào)。
原文標(biāo)題:What's a Merge Queue and Why Use it?,作者:Wakatepe-mergify