1 Punkte von GN⁺ 4 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Copybara ist ein intern bei Google verwendetes Tool, das Quellcode zwischen mehreren Repositories transformiert und verschiebt. Es wird unter anderem genutzt, um confidential Repositories und public Repositories zu synchronisieren.
  • Ein Repository wird als authoritatives Repository ausgewählt, um eine Single Source of Truth beizubehalten. Beiträge können jedoch in jedem Repository eingehen, und Releases können ebenfalls aus jedem Repository erstellt werden.
  • Der wichtigste Anwendungsfall ist das wiederholte Verschieben von Code. Unterstützt werden Workflows, bei denen Teile des Codes aus einem confidential Repository in ein public Repository übernommen oder Änderungen aus einem public Repository in das authoritative Repository zurückgeführt werden.
  • Copybara arbeitet stateless, indem es den Zustand nicht auf einem separaten Server, sondern in Labels in Commit-Nachrichten des Ziel-Repositorys speichert. So können mehrere Nutzer oder Dienste mit derselben Konfiguration und denselben Repositories dieselben Ergebnisse erzielen.
  • Der derzeit unterstützte Repository-Typ ist Git; das Lesen aus Mercurial ist eine experimentelle Funktion. Durch die erweiterbare Struktur lassen sich eigene Origins und Destinations hinzufügen.

Welches Problem Copybara löst

  • Copybara ist ein Tool zum Verschieben und Transformieren von Quellcode zwischen Repositories.
  • Es gibt Fälle, in denen Quellcode in mehreren Repositories vorhanden sein muss. Copybara ermöglicht es, Code zwischen solchen Repositories zu transformieren und zu verschieben.
  • Ein typisches Beispiel sind Projekte, bei denen ein confidential Repository und ein public Repository synchron gehalten werden.
  • Die häufigste Nutzung besteht darin, Code wiederholt von einem Repository in ein anderes zu verschieben.
  • Es kann auch verwendet werden, um Code einmalig in ein neues Repository zu übertragen.

Authoritatives Repository und Beitragsfluss

  • Copybara muss eines der Repositories als authoritative repository auswählen.
    • Dies ist die Voraussetzung dafür, dass immer eine source of truth existiert.
  • Beiträge können in jedem Repository erfolgen.
  • Releases können ebenfalls aus jedem Repository erstellt werden.
  • Wenn in einem nicht-authoritativen Repository eine Änderung entsteht, kann Copybara diese Änderung transformieren und an die passende Stelle im authoritativen Repository verschieben.
    • Ein Beispiel ist eine Änderung, die ein Contributor in einem public Repository erstellt hat.
    • Merge-Konflikte werden genauso behandelt wie veraltete Änderungen innerhalb des authoritativen Repositorys.

Anwendungsbeispiele

  • Beispiele für die Nutzung von Copybara sind unter anderem:
    • Teile des Codes aus einem confidential Repository in ein public Repository übernehmen
    • Code aus einem public Repository in ein confidential Repository übernehmen
    • Änderungen aus einem nicht-authoritativen Repository in das authoritative Repository übernehmen
  • Eine Beispielkonfiguration definiert Origin und Destination mit core.workflow.
    • Als Origin wird git.github_origin mit master aus https://github.com/google/copybara.git verwendet.
    • Als Destination wird git.destination mit file:///tmp/foo verwendet.
    • destination_files zielt auf third_party/copybara/** ab und schließt README_INTERNAL.txt aus.
    • Mit core.replace und core.move werden BUILD-Dateipfade ersetzt und Verzeichnisse verschoben.
  • Ein Ausführungsbeispiel besteht darin, ein bare Git-Repository zu erstellen und anschließend copybara copy.bara.sky auszuführen.

Zustandsspeicherung und Repository-Unterstützung

  • Eine der wichtigsten Eigenschaften von Copybara ist seine stateless Architektur.
  • Genauer gesagt speichert es den Zustand im Ziel-Repository.
    • Speicherort sind Labels in Commit-Nachrichten.
  • Dadurch können mehrere Nutzer oder Dienste mit derselben Kombination aus Konfiguration und Repositories dieselben Ergebnisse erzielen.
  • Der derzeit unterstützte Repository-Typ ist Git.
  • Das Lesen aus Mercurial-Repositories ist möglich, aber noch experimentell.
  • Über die erweiterbare Architektur lassen sich für nahezu jeden Anwendungsfall bespoke Origins und Destinations hinzufügen.
  • Offizielle Unterstützung für weitere Repository-Typen soll künftig ergänzt werden.

Installation und Build

  • Der einfachste Einstieg ist die Nutzung eines wöchentlichen Snapshot Release mit vorgebauten Binaries.
  • Wer eine unveröffentlichte Version nutzen möchte, muss von HEAD bauen.
    • JDK 11 muss installiert sein.
    • Bazel muss installiert sein.
    • Quellcode mit git clone https://github.com/google/copybara.git klonen.
    • Mit bazel build //java/com/google/copybara bauen.
    • Ein ausführbares Uber-JAR wird mit bazel build //java/com/google/copybara:copybara_deploy.jar erzeugt.
    • Tests können mit bazel test //... ausgeführt werden.
  • Einige Tests erfordern installierte Basistools wie Mercurial oder Quilt.
    • Wenn ein Pull Request nicht mit dem jeweiligen Modul zusammenhängt, können diese Tests übersprungen werden.
    • CI führt alle Tests aus.
  • Unter Arch Linux kann das Paket aur/copybara-git verwendet werden.

Vorgebautes Copybara in Bazel verwenden

  • Das wöchentliche Snapshot Release kann in Bazel verwendet werden.
  • Copybara wird mit class file version 65.0 bereitgestellt und muss daher mit Java Runtime 21 oder höher ausgeführt werden.
    • In .bazelrc muss run --java_runtime_version=remotejdk_21 hinzugefügt werden.
  • Das Release Artifact wird mit http_jar heruntergeladen.
    • In WORKSPACE wird load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") verwendet.
    • In MODULE.bazel wird http_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") verwendet.
  • In WORKSPACE oder MODULE.bazel wird die Stelle [version] ausgefüllt und copybara_deploy.jar angegeben.
  • In der BUILD-Datei wird ein java_binary deklariert, das com.google.copybara.Main als main class verwendet.
  • Ein Ausführungsbeispiel ist bazel run //tools:copybara -- migrate copy.bara.sky.

Source-Build als externes Bazel-Repository

  • Für Copybara-Abhängigkeiten werden Convenience-Makros bereitgestellt.
  • In WORKSPACE wird http_archive hinzugefügt und die Werte {{ sha256sum }} und {{ commit }} werden eingetragen.
  • Danach werden die folgenden Makros geladen und aufgerufen:
    • copybara_repositories()
    • copybara_maven_repositories()
    • copybara_go_repositories()
  • Innerhalb des Workspace kann es mit bazel run @com_github_google_copybara//java/com/google/copybara -- <args...> gebaut und ausgeführt werden.

Docker verwenden

  • Copybara mit Docker zu bauen und auszuführen ist derzeit experimentell.
  • Der Build erfolgt mit docker build --rm -t copybara ..
  • Die Ausführung erfolgt vom Root-Verzeichnis des Zielcodes aus in der Form docker run -it -v "$(pwd)":/usr/src/app copybara help.
  • Statt Argumenten beim Start des Containers können Umgebungsvariablen verwendet werden.
    • COPYBARA_SUBCOMMAND=migrate: ändert den auszuführenden Befehl, Standardwert ist migrate.
    • COPYBARA_CONFIG=copy.bara.sky: gibt den Pfad zur Konfigurationsdatei an, Standardwert ist copy.bara.sky im Root-Verzeichnis.
    • COPYBARA_WORKFLOW=default: gibt den auszuführenden Workflow an, Standardwert ist default.
    • COPYBARA_SOURCEREF='': gibt die sourceref an, standardmäßig nicht gesetzt.
    • COPYBARA_OPTIONS='': gibt Copybara-Optionen an, standardmäßig nicht gesetzt.
  • Git-Konfiguration und SSH-Anmeldedaten können mit dem Docker-Container geteilt werden.
    • Ein Beispiel ist das Mounten von ~/.gitconfig, ~/.ssh und SSH_AUTH_SOCK in den Container.

Dokumentation und Kontakt

1 Kommentare

 
GN⁺ 4 시간 전
Meinungen auf Hacker News
  • Interessant war, dass dieser Beitrag genau kurz nachdem ich einen Patch für Perforce-Unterstützung, den ich für den Einsatz in einem Spieleentwicklungsstudio gebaut hatte, als Open Source veröffentlicht hatte, erschien.
    Wenn man bedenkt, dass Copybara hauptsächlich für die Verteilung von internem Google-Code genutzt wird und dieser Code in Piper liegt, das mit Perforce zu tun hat, fand ich es ziemlich überraschend, dass es keine Perforce-Unterstützung gibt und im Wesentlichen nur Git sinnvoll unterstützt wird.
    Bevor ich den PR erstellt habe, habe ich mir die Git-Historie angesehen und viele Gerrit-Change-ID-Markierungen gesehen. Da hatte ich Sorge, dass es irgendwo ein Gerrit-Code-Review-System gibt, auf das ich keinen Zugriff habe, und dass mein PR vielleicht nicht upstream übernommen wird.
    Schade ist auch, dass es kein Gerrit/Rietveld für Perforce gibt, aber man kann nicht alles haben.
    https://github.com/google/copybara/pull/347

    • Einer der Gründe, warum Gerrit/Rietveld keine Perforce-Unterstützung hat, ist, dass Google diese Tools nicht für Codeänderungen verwendet, die in Piper gespeichert sind. Stattdessen nutzt man Critique.
      https://abseil.io/resources/swe-book/html/ch19.html
      https://read.engineerscodex.com/p/how-google-takes-the-pain-...
      Unter externen Tools habe ich bisher nichts gefunden, das so gut ist wie Critique, und ich bin überrascht, dass die dürftigen PR-Review-Tools von GitHub für die meisten akzeptabel sind. Falls jemand ein Tool auf ähnlichem Niveau kennt, würde ich gern davon hören.
      Als ich Google vor ein paar Jahren verlassen habe, habe ich ziemlich gründlich gesucht, und https://codeapprove.com/ kam dem am nächsten, aber es fehlte immer noch vieles.
    • Piper ist kein Fork von Perforce. Es ist zwar API-kompatibel mit Perforce, aber eine komplett andere Implementierung.
    • Dieses Repository nimmt PRs an. Allerdings werden sie intern gemergt und anschließend wieder nach außen exportiert.
      Open-Source-Projekte wie gVisor oder Bazel, die im internen Monorepo leben, werden mit kleinen Unterschieden im Großen und Ganzen ähnlich betrieben.
  • Ein weiteres interessantes Tool in diesem Bereich: Rust verwendet für die Commit-Synchronisierung ein Tool namens Josh.
    https://josh-project.dev
    Dazu gibt es auch einen Blogbeitrag aus dem Rust-Umfeld:
    https://blog.rust-lang.org/inside-rust/2026/06/04/how-josh-h...
    Bei Meta gab es früher ein Open-Source-Tool namens fbshipit, laut dem öffentlichen Repository wird es aber nicht mehr verwendet.
    https://github.com/facebookarchive/fbshipit
    Gibt es in diesem Bereich noch andere Tools?

  • Ist das auch praktisch, wenn mehrere Repositories ein wenig Code gemeinsam nutzen möchten, es sich aber nicht lohnt, dafür eine Library auszulagern, Referenzen zu setzen, Versions-Releases zu veröffentlichen und abhängige Repositories zu aktualisieren?
    Ich frage mich zum Beispiel, ob man damit einen Ordner mit gemeinsamen Domain-Modellen einfach von einem Haupt-Repository in andere Repositories synchronisieren kann.
    Das entspricht eher der Go-Philosophie: „Lieber ein wenig kopieren als massenhaft Abhängigkeiten haben.“

    • Es wird hauptsächlich verwendet, um externe Open-Source-Projekte mit dem internen Monorepo zu synchronisieren. Die Richtlinie verlangt, Quellcode zu importieren statt Build-Artefakte, Ausnahmen sind aber möglich.
      Manche Projekte werden im Monorepo entwickelt und mit Copybara nach außen exportiert.
      Unser Team nutzt es intern auch für die Versionsverwaltung eines Satzes von Starlark-Regeln.
    • Es ist ein Tool für den Fall, dass man intern ein Monorepo hat und einen Teil davon als Open Source veröffentlichen möchte. Der Code soll aber weiterhin im Monorepo bleiben, also ist das die Lösung.
      Ein öffentliches Repository als Abhängigkeit eines internen privaten Repositories zu haben, ist aus Entwicklungssicht ziemlich mühsam. Wenn solche Abhängigkeiten baumartig wachsen, wird es wirklich zum Kopfschmerz.
    • Mit Copybara kann man so etwas zwar machen, aber wenn man es so nutzt, dürfte es leicht nervig und langweilig werden. Es kann sogar umständlicher sein, als eine Library auszulagern oder ein paar Dateien in ein separates Repository zu schieben.
  • Ich nutze es schon ziemlich lange, vor allem dann, wenn ein Tool, das innerhalb eines großen Projekts entstanden ist, groß genug für ein eigenständiges Release geworden ist.
    Es ist leistungsfähig genug, um den gesamten bidirektionalen Deployment-Prozess mit Export und erneutem Import von Code abzuwickeln, aber das ist so umständlich, dass ich darauf verzichte.
    Ich verwende es meist für einen einfachen einmaligen Export, bei dem ich einen Ordner aus dem ursprünglichen Repository herauslöse, aber die Historie bewahre. Die weitere Entwicklung wandert danach ins neue Repository.
    Ich bin zufrieden, weil Git blame auch dann funktioniert, wenn die neue Projektstruktur völlig anders ist.

    • Dieses unidirektionale Muster ist tatsächlich auch die Art, wie es intern bei Google genutzt wird: eine Synchronisierung vom Monorepo nach außen zu GitHub.
      Bidirektional wird es unübersichtlich, weil Transformationen wie Pfad-Remapping, Dateiausschlüsse oder das Entfernen von Headern in eine Richtung einfach sind, sich aber nicht immer sauber zurücktransformieren lassen.
      Wenn beide Seiten auseinanderlaufen, beginnt Copybaras Baseline-Tracking verwirrende Ergebnisse zu liefern. Semantisch gleiche Commits erzeugen nach der Transformation nämlich unterschiedliche SHAs.
      Wissenswert ist, dass das „Bewahren“ der Historie keine echte Transplantation ist, sondern darauf basiert, die neu geschriebenen Commits per Cherry-Pick zu übernehmen. Dateiinhalte und Autoreninformationen werden übertragen, daher funktioniert Git blame, aber die SHAs entstehen neu.
      Copybara legt die ursprüngliche SHA im Commit-Message-Trailer GitOrigin-RevId ab, was später nützlich ist, wenn man Commits zwischen Repositories abgleichen muss.
  • Fortschritt über mehr als 52 Jahre hinweg :-)
    Juli 2026: Google copybara ermöglicht es, Code zwischen zwei Produktions-Repositories zu verschieben.
    März 1974: IBM COPY ermöglichte es, Code zwischen zwei Produktions-Partitioned-Datasets zu verschieben. OS/MVT und OS/VS2 TSO Data Utilities COPY, FORMAT, LIST, MERGE User's Guide and Reference https://www.computinghistory.org.uk/downloads/8987

  • Bei Dagster haben wir Copybara genutzt, um ein Hub-and-Spoke-Modell aufzubauen, bei dem öffentliche Repositories innerhalb eines größeren internen Monorepos leben können. Es funktionierte, erforderte aber ziemlich viele Umwege.
    https://dagster.io/blog/monorepos-the-hub-and-spoke-model-an...

  • Wenn man nur Repository-Synchronisierung ohne Ausschlüsse oder Transformationen braucht, würde ich es wohl nicht verwenden. Im Moment kann es passen, aber wenn es wie kaniko oder viele Google-Produkte/-Tools archiviert oder eingestellt wird, könnte das problematisch werden.
    GitLab bietet eine sehr einfache Möglichkeit, von GitLab nach GitHub oder zu anderen Git-Anbietern/-Servern zu spiegeln.

    • Ich halte es für wirklich unwahrscheinlich, dass Copybara eingestellt wird. Soweit ich weiß, ist es ein ziemlich zentrales Tool für google3 und für die Art, wie große Open-Source-Projekte gepflegt und vendored werden.
    • Genau, Copybara ist eher ein Tool dafür, Transformationen in eine oder beide Richtungen vorzunehmen.
      Zum Beispiel externes bzl in eine mit internem Blaze-BUILD kompatible Form umzuwandeln oder zwischen externen Imports und internen Imports im third_party-Stil zu wechseln.
      Für einen reinen Mirror ist Copybara überdimensioniert.
  • Gut. Ich habe vor etwa fünf Jahren mit verschachtelten Git-Repositories und Skripten etwas Ähnliches gebaut, um private und öffentliche Repositories gemeinsam zu handhaben.
    Meine Shell-Skripte hatten natürlich keinen Google-Maßstab.

    • Bei mir war es ähnlich. Zuerst dachte ich, es wäre ein Wrapper um git subtree, aber wie es aussieht, macht es deutlich mehr.
      Zum Beispiel gibt es auch eine Funktion, um während der Synchronisierung die E-Mail-Adresse des Commit-Autors zu ändern.