Google Copybara:在儲存庫之間轉換與移動程式碼

Google Copybara:在儲存庫之間轉換與移動程式碼

Google Copybara 可實現儲存庫之間的同步程式碼移動

Google Copybara 是一個用於在儲存庫之間轉換與移動原始碼的工具。它主要用於維持機密(私有)儲存庫與公開儲存庫之間的同步,確保程式碼可以存在於多個位置,同時維持單一且具權威性的事實來源(source of truth)。

核心功能與使用案例

Copybara 允許開發者在移動程式碼的同時對內容進行轉換。關鍵使用案例包括:

  • 私有轉公開同步: 將機密儲存庫中的特定程式碼區塊匯入到公開儲存庫中。
  • 公開轉私有同步: 將程式碼從公開儲存庫匯入回機密儲存庫中。
  • 貢獻管理: 將變更從非權威儲存庫(例如公開貢獻者的 PR)移動到權威儲存庫,並轉換程式碼以符合內部結構。
  • 一次性遷移: 在保留歷史紀錄的同時,將程式碼一次性移動到新儲存庫。

技術架構與狀態管理

Copybara 的設計是無狀態的(stateless)。它並非維護一個外部資料庫來記錄已移動的內容,而是透過在提交訊息(commit messages)中使用標籤(labels)來將狀態儲存在目標儲存庫中。這種架構允許多個使用者或自動化服務針對相同的儲存庫執行相同的配置,並獲得一致的結果。

目前,Copybara 正式支援 Git 儲存庫,並對 Mercurial 提供實驗性支援。其可擴展的架構旨在允許針對各種使用案例添加自定義的來源(origins)與目的地(destinations)。

配置與實作

Copybara 使用一種配置語言(通常是 .sky 檔案)來定義工作流(workflows)。一個工作流定義了來源、目的地、要移動的檔案(使用 globs)以及要套用的轉換規則。

工作流邏輯範例:

core.workflow(
    name = "default",
    origin = git.github_origin(
      url = "https://github.com/google/copybara.git",
      ref = "master",
    ),
    destination = git.destination(
        url = "file:///tmp/foo",
    ),
    destination_files = glob(["third_party/copybara/**"], exclude = ["README_INTERNAL.txt"]),
    transformations = [
        core.replace(
                before = "//third_party/bazel/bashunit",
                after = "//another/path:bashunit",
                paths = glob(["**/BUILD"])),
        core.move("", "third_party/copybara")
    ],
)

安裝與部署選項

根據環境的不同,Copybara 可以透過幾種方式進行部署:

  • 預編譯二進位檔: 每週的快照版本(snapshot releases)可在 GitHub 上取得,需要 Java Runtime 21 或更高版本。
  • el-Bazel 建置: 可以使用 JDK 11 與 Bazel 從原始碼編譯該工具。它也可以透過提供的便利宏(macros)作為外部 Bazel 儲存庫進行整合。
  • Docker: 提供實驗性的 Docker 映像檔,允許使用者透過容器執行 Copybara。此方法支援環境變數(例如 COPYBARA_CONFIGCOPYBARA_WORKFLOW)來控制執行,並允許掛載 .gitconfig 與 SSH 憑證以進行儲存庫存取。

社群洞察與替代方案

使用者與開發者針對 Copybara 與其他版本控制策略的效用提出了幾種觀點:

  • Monorepo 生產力: 一些使用者報告,在使用 Copybara 管理內部 monorepo 的公開面向組件時,生產力有顯著提升。
  • 歷史紀錄保留: 它被認為是執行「發完即忘」(fire and forget)匯出的有效工具,可以在將資料夾移動到新儲存庫的同時保留 Git blame 歷史紀錄。
  • Alternatives: 討論點包括使用 GitLab 的內建鏡像功能、Git submodules 或 Git subtrees。其他提到的專門工具包括 Josh(由 Rust 專案使用)和來自 Meta 的已封存的 fbshipit
  • Trade-offs: 一些貢獻者警告,對於不需要轉換或排除規則的簡單儲存庫鏡像,較簡單的內建供應商工具可能更可靠。

"如果你的唯一需求只是同步儲存庫,且不需要排除或轉換,我不會費心去用它... GitLab 有非常簡單的方式可以將內容從 GitLab 鏡像到 GitHub 或其他 Git 供應商/伺服器"

"我見過許多團隊在於具有公開部分的 monorepo 中進行協作時,獲得了顯著的生產力提升。"

Sources