在現代軟體開發中,許多大型企業傾向於採用 Monorepo 模式,即將多個專案或所有程式碼集中在單一的巨型儲存庫中,以簡化依賴管理並提高跨團隊協作效率。然而,當儲存庫規模達到極端量級時,傳統的 Git 分散式版本控制特性反而變成了負擔。Uber 正面臨這樣的挑戰,其支持 Go、Java、Python 以及各類行動端開發的 Monorepo 規模極大,導致開發者與自動化系統在執行基礎的 Git 操作時,面臨巨大的資源消耗與時間延遲。
背景與挑戰
在導入新方案之前,Uber 的自動化系統每天需要執行數百萬次 Git 操作,包括讀取檔案、驗證變更以及計算合併基底(Merge Base,指兩個分支共同的最近祖先,用於決定如何合併程式碼)。在傳統的工作流中,每個需要執行 Git 指令的服務都必須在本地端維護一份完整的儲存庫檢出(Checkout),也就是將遠端伺服器的程式碼完整複製到本地磁碟上。
這種模式在超大型儲存庫中會導致嚴重的基礎設施瓶頸。以 Uber 的 Go 語言 Monorepo 為例,單次克隆(Clone)操作大約需要 15 分鐘,且單個執行環境需消耗 6 個 CPU 核心、32 GB 記憶體以及超過 40 GB 的磁碟空間。對於需要頻繁啟動的自動化任務或 CI 管道來說,這種長達 10 到 20 分鐘的冷啟動時間(Cold Start)極大地降低了開發效率,並造成了巨大的硬體資源浪費。
GitFarm 的核心設計與運作方式
為了徹底解決本地克隆的效能問題,Uber 開發了名為 GitFarm 的平台。GitFarm 的核心理念是將 Git 操作服務化(Git as a Service),將原本分散在各個客戶端系統的 Git 指令執行權限,集中到一個高效能的共享服務中。需要強調的是,GitFarm 並非一個新的版本控制系統,而是一個充當集中式 Git 用戶端的代理服務。
在架構上,GitFarm 透過高效率的 gRPC API(一種由 Google 開發的遠端過程調用框架,能提供低延遲、高吞吐量的通訊)來接收請求。當外部服務需要執行 Git 操作時,請求會先經過 Gateway 進行身分驗證與授權,隨後被路由至後端叢集。後端叢集會在隔離且臨時的沙箱環境(Ephemeral Sandboxes)中執行指令。
為了消除初始化時間,GitFarm 採用了預熱池(Pooling)機制。後端會維護一份裸儲存庫(Bare Repository,僅包含版本歷史而不包含工作目錄的儲存庫)並透過推送更新與定期抓取保持同步。同時,系統會預先準備好一批檢出目錄與沙箱容器。當請求到達時,GitFarm 能直接將預熱好的檢出目錄掛載到可用沙箱中,使提供可用環境的時間從 15 分鐘縮短至 500 毫秒以內。
此外,針對複雜的工作流,GitFarm 支援雙向 gRPC 串流會話(Bidirectional gRPC Streaming Sessions)。這允許客戶端在同一個檢出環境中連續執行多個指令,例如先抓取分支、計算合併基底,最後推送參考路徑,而不需要在每個步驟之間重新初始化儲存庫狀態。
實務影響與效能提升
GitFarm 的導入為 Uber 帶來了顯著的資源節省與速度提升。在一個負責程式碼所有權(Code Ownership)的服務中,導入 GitFarm 後,該服務不再需要在 6 台主機上維護本地檢出,CPU 消耗從 70 多個核心大幅下降至 16 個,記憶體使用量從 400 GB 縮減至 32 GB,啟動時間則從 20 分鐘縮短至一分鐘以內。
在合規審計服務的案例中,該服務每小時需處理 1 萬至 2 萬個事件,涉及 9,000 個儲存庫。原先使用 Buildkite 構建工具時,由於涉及排程、工作區初始化與儲存庫同步,中位數延遲高達 110 到 160 秒;切換至 GitFarm 後,由於消除了上述冗餘開銷,延遲降低至 20 到 30 秒。
技術脈絡與未來展望
GitFarm 的設計不僅解決了目前的基礎設施壓力,也為未來 AI 輔助開發奠定了基礎。隨著 Coding Agent(程式碼自動化代理)的普及,AI 代理會頻繁且併發地執行搜尋、建分支、對比差異(Diff)、實驗與驗證等操作,這將對 Git 基礎設施造成比人類開發者高出數倍的負荷。透過將 Git 操作集中化與服務化,Uber 可以更有效地管理這些高頻率的請求。
目前 GitFarm 已於 2025 年初投入生產環境,未來的發展路徑包括支援 Git 輸出串流、稀疏檢出(Sparse Checkouts,僅下載儲存庫中特定目錄以減少空間佔用)、裸工作區以及與提交隊列(SubmitQueue)的深度整合,以進一步優化超大規模開發環境的體驗。
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。