Google Copybara: Code zwischen Repositories verschieben
(github.com/google)- 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_originmitmasteraushttps://github.com/google/copybara.gitverwendet. - Als Destination wird
git.destinationmitfile:///tmp/fooverwendet. destination_fileszielt aufthird_party/copybara/**ab und schließtREADME_INTERNAL.txtaus.- Mit
core.replaceundcore.movewerden BUILD-Dateipfade ersetzt und Verzeichnisse verschoben.
- Als Origin wird
- Ein Ausführungsbeispiel besteht darin, ein bare Git-Repository zu erstellen und anschließend
copybara copy.bara.skyauszufü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.
- Releases werden automatisch erstellt.
- Es gibt keine Garantie für manuelle Tests, Versionskompatibilität oder Korrektheit.
- Releases können unter
https://github.com/google/copybara/releasesausgewählt werden.
- 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.gitklonen. - Mit
bazel build //java/com/google/copybarabauen. - Ein ausführbares Uber-JAR wird mit
bazel build //java/com/google/copybara:copybara_deploy.jarerzeugt. - 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-gitverwendet 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
.bazelrcmussrun --java_runtime_version=remotejdk_21hinzugefügt werden.
- In
- Das Release Artifact wird mit
http_jarheruntergeladen.- In
WORKSPACEwirdload("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")verwendet. - In
MODULE.bazelwirdhttp_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")verwendet.
- In
- In
WORKSPACEoderMODULE.bazelwird die Stelle[version]ausgefüllt undcopybara_deploy.jarangegeben. - In der BUILD-Datei wird ein
java_binarydeklariert, dascom.google.copybara.Mainals 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
WORKSPACEwirdhttp_archivehinzugefü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 istmigrate.COPYBARA_CONFIG=copy.bara.sky: gibt den Pfad zur Konfigurationsdatei an, Standardwert istcopy.bara.skyim Root-Verzeichnis.COPYBARA_WORKFLOW=default: gibt den auszuführenden Workflow an, Standardwert istdefault.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,~/.sshundSSH_AUTH_SOCKin den Container.
- Ein Beispiel ist das Mounten von
Dokumentation und Kontakt
- Die Dokumentation ist noch in Arbeit.
- Verfügbare Materialien sind:
- Fragen können über die mailing list gestellt werden.
- Um Bazel-Testfehler ohne
catder Logdatei zu sehen, kanntest --test_output=streamedzu~/.bazelrchinzugefügt werden.
1 Kommentare
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
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.
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?
Später wurde es in Git selbst gemergt.
https://manpages.debian.org/testing/git-man/git-subtree.1.en...
https://docs.github.com/en/get-started/using-git/about-git-s...
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.“
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.
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.
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 blameauch dann funktioniert, wenn die neue Projektstruktur völlig anders ist.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-RevIdab, 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.
Zum Beispiel externes
bzlin eine mit internem Blaze-BUILDkompatible Form umzuwandeln oder zwischen externen Imports und internen Imports imthird_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.
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.