Google Copybara : déplacer du code entre dépôts
(github.com/google)- Copybara est un outil utilisé en interne chez Google pour transformer et déplacer du code source entre plusieurs dépôts, notamment afin de synchroniser des dépôts confidentiels et publics
- Il permet de conserver une source unique de vérité en choisissant un dépôt comme dépôt d’autorité, tout en acceptant des contributions depuis n’importe quel dépôt et en permettant de créer des releases depuis n’importe lequel
- Son principal cas d’usage est le déplacement récurrent de code, avec des flux permettant d’importer une partie du code d’un dépôt confidentiel vers un dépôt public, ou de rapatrier des changements d’un dépôt public vers le dépôt faisant autorité
- Copybara adopte une approche stateless : au lieu de stocker son état sur un serveur séparé, il l’enregistre dans les labels des messages de commit du dépôt cible, ce qui permet à plusieurs utilisateurs ou services d’obtenir le même résultat avec la même configuration et les mêmes dépôts
- Le type de dépôt actuellement pris en charge est Git ; la lecture depuis Mercurial est expérimentale, et son architecture extensible permet d’ajouter des origines et destinations personnalisées
Le problème que résout Copybara
- Copybara est un outil destiné au déplacement et à la transformation de code source entre dépôts
- Il arrive que du code source doive exister dans plusieurs dépôts ; Copybara permet de transformer et de déplacer ce code entre ces dépôts
- Un cas représentatif est celui d’un projet maintenant synchronisés un dépôt confidentiel et un dépôt public
- Le mode d’utilisation le plus courant consiste à déplacer du code de manière répétée d’un dépôt vers un autre
- Il peut aussi être utilisé pour déplacer du code une seule fois vers un nouveau dépôt
Dépôt d’autorité et flux de contributions
- Copybara exige de choisir l’un des dépôts comme authoritative repository
- C’est une condition pour qu’il existe toujours une seule source of truth
- Les contributions peuvent venir de n’importe quel dépôt
- Les releases peuvent aussi être créées depuis n’importe quel dépôt
- Lorsqu’un changement intervient dans un dépôt ne faisant pas autorité, Copybara peut le transformer et le déplacer vers l’emplacement approprié dans le dépôt d’autorité
- L’exemple donné est un changement créé par un contributeur du dépôt public
- Les conflits de merge sont traités de la même manière que les anciens changements dans le dépôt d’autorité
Exemples d’utilisation
- Les exemples d’utilisation de Copybara incluent :
- importer une partie du code d’un dépôt confidentiel vers un dépôt public
- importer le code d’un dépôt public vers un dépôt confidentiel
- importer des changements d’un dépôt non autoritaire vers un dépôt faisant autorité
- Un exemple de configuration définit l’origine et la destination avec
core.workflow- L’origine utilise
git.github_originavec la branchemasterdehttps://github.com/google/copybara.git - La destination utilise
git.destinationavecfile:///tmp/foo destination_filesciblethird_party/copybara/**et exclutREADME_INTERNAL.txtcore.replaceetcore.moveeffectuent la substitution de chemin du fichier BUILD et le déplacement de répertoire
- L’origine utilise
- Un exemple d’exécution consiste à créer un dépôt Git bare, puis à lancer
copybara copy.bara.sky
Stockage de l’état et prise en charge des dépôts
- L’une des principales caractéristiques de Copybara est son architecture stateless
- Plus précisément, l’état est stocké dans le dépôt cible
- L’emplacement de stockage est constitué par les labels des messages de commit
- Cette approche permet à plusieurs utilisateurs ou services d’obtenir le même résultat avec la même combinaison de configuration et de dépôts
- Le type de dépôt actuellement pris en charge est Git
- La lecture depuis des dépôts Mercurial est possible, mais reste expérimentale
- Grâce à une architecture extensible, il est possible d’ajouter des origines et destinations sur mesure pour presque tous les cas d’usage
- La prise en charge officielle d’autres types de dépôts sera ajoutée ultérieurement
Installation et build
- Le moyen le plus simple de démarrer consiste à utiliser une snapshot release hebdomadaire incluant des binaires précompilés
- Les releases sont créées automatiquement
- Il n’y a aucune garantie de tests manuels, de compatibilité de version ni d’exactitude
- Les releases sont disponibles sur
https://github.com/google/copybara/releases
- Pour utiliser une version non publiée, il faut builder depuis HEAD
- Installation de JDK 11 requise
- Installation de Bazel requise
- Cloner les sources avec
git clone https://github.com/google/copybara.git - Builder avec
bazel build //java/com/google/copybara - L’uberjar exécutable est généré avec
bazel build //java/com/google/copybara:copybara_deploy.jar - Les tests peuvent être lancés avec
bazel test //...
- Certains tests nécessitent l’installation d’outils sous-jacents comme Mercurial ou Quilt
- Si une Pull Request ne concerne pas ces modules, ces tests peuvent être ignorés
- La CI exécute tous les tests
- Sous Arch Linux, le paquet
aur/copybara-gitest disponible
Utiliser Copybara précompilé avec Bazel
- Les snapshot releases hebdomadaires peuvent être utilisées avec Bazel
- Copybara est fourni avec la class file version 65.0 ; il doit donc être exécuté avec Java Runtime 21 ou plus récent
- Il faut ajouter
run --java_runtime_version=remotejdk_21à.bazelrc
- Il faut ajouter
- L’artefact de release est téléchargé avec
http_jar- Dans
WORKSPACE, utiliserload("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") - Dans
MODULE.bazel, utiliserhttp_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
- Dans
- Dans
WORKSPACEouMODULE.bazel, renseigner l’emplacement[version]pour désignercopybara_deploy.jar - Dans le fichier BUILD, déclarer un
java_binaryutilisantcom.google.copybara.Maincomme main class - Un exemple d’exécution est
bazel run //tools:copybara -- migrate copy.bara.sky
Builder les sources comme dépôt Bazel externe
- Des macros pratiques sont fournies pour les dépendances de Copybara
- Ajouter
http_archiveàWORKSPACEet renseigner les valeurs{{ sha256sum }}et{{ commit }} - Ensuite, charger et appeler les macros suivantes :
copybara_repositories()copybara_maven_repositories()copybara_go_repositories()
- Dans le workspace, il est possible de builder et d’exécuter avec
bazel run @com_github_google_copybara//java/com/google/copybara -- <args...>
Utilisation avec Docker
- Le build et l’exécution de Copybara avec Docker sont actuellement expérimentaux
- Le build s’effectue avec
docker build --rm -t copybara . - L’exécution se fait depuis la racine du code cible sous la forme
docker run -it -v "$(pwd)":/usr/src/app copybara help - Des variables d’environnement peuvent être utilisées à la place des arguments d’exécution du conteneur
COPYBARA_SUBCOMMAND=migrate: change la commande exécutée ; valeur par défaut :migrateCOPYBARA_CONFIG=copy.bara.sky: indique le chemin du fichier de configuration ; valeur par défaut :copy.bara.skyà la racineCOPYBARA_WORKFLOW=default: indique le workflow à exécuter ; valeur par défaut :defaultCOPYBARA_SOURCEREF='': indique la sourceref ; aucune valeur par défautCOPYBARA_OPTIONS='': indique les options Copybara ; aucune valeur par défaut
- La configuration Git et les identifiants SSH peuvent être partagés avec le conteneur Docker
- L’exemple consiste à monter
~/.gitconfig,~/.sshetSSH_AUTH_SOCKdans le conteneur
- L’exemple consiste à monter
Documentation et contact
- La documentation est encore en cours de rédaction
- Les ressources fournies sont les suivantes :
- Les questions peuvent être posées sur la mailing list
- Pour voir les erreurs des tests Bazel sans faire de
catsur le fichier de logs, il est possible d’ajoutertest --test_output=streamedà~/.bazelrc
1 commentaires
Avis de Hacker News
C’était amusant de voir cet article paraître juste après que j’ai publié en open source un patch de prise en charge de Perforce que j’avais créé pour l’utiliser dans un studio de développement de jeux.
Quand on sait que le principal usage de Copybara est le déploiement de code interne de Google, et que ce code se trouve dans Piper, qui a un lien avec Perforce, j’ai trouvé assez surprenant qu’il n’y ait pas de prise en charge de Perforce et seulement une prise en charge réellement significative de Git.
Avant de créer la PR, en regardant l’historique Git, j’ai vu beaucoup de marqueurs Gerrit Change-ID, donc je me suis aussi demandé s’il existait quelque part un système de revue de code Gerrit auquel je n’ai pas accès, et si ma PR ne serait pas intégrée upstream.
C’est aussi dommage qu’il n’y ait pas de Gerrit/Rietveld pour Perforce, mais on ne peut pas tout avoir.
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-...
Parmi les outils externes, je n’ai encore rien trouvé d’aussi bon que Critique, et je suis surpris que les maigres outils de revue de PR de GitHub soient acceptés par la plupart des gens. Si quelqu’un connaît un outil d’un niveau comparable, je serais curieux d’en entendre parler.
Quand j’ai quitté Google il y a quelques années, j’avais cherché assez minutieusement, et https://codeapprove.com/ était ce qui s’en rapprochait le plus, mais il lui manquait encore beaucoup de choses.
Les projets open source comme gVisor ou Bazel, qui vivent dans le monorepo interne, fonctionnent globalement de manière similaire, même s’il y a quelques différences.
Parmi les autres outils intéressants dans ce domaine, Rust utilise un outil appelé Josh pour la synchronisation des commits.
https://josh-project.dev
Il y a aussi un billet de blog côté Rust.
https://blog.rust-lang.org/inside-rust/2026/06/04/how-josh-h...
Meta avait autrefois un outil open source appelé fbshipit, mais d’après le dépôt public il n’est plus utilisé.
https://github.com/facebookarchive/fbshipit
Existe-t-il d’autres outils dans ce domaine ?
Il a ensuite été intégré à Git lui-même.
https://manpages.debian.org/testing/git-man/git-subtree.1.en...
https://docs.github.com/en/get-started/using-git/about-git-s...
Est-ce aussi pratique quand plusieurs dépôts veulent partager un peu de code, mais que ça ne vaut pas la peine d’en faire une bibliothèque séparée, d’ajouter une référence, de publier des versions et de mettre à jour les dépôts dépendants ?
Par exemple, je me demande si on peut l’utiliser pour simplement synchroniser un dossier contenant un modèle de domaine commun depuis un dépôt principal vers d’autres dépôts.
C’est un usage proche de la philosophie à la Go : « mieux vaut copier un peu que d’empiler les dépendances ».
Certains projets sont développés dans le monorepo puis exportés vers l’extérieur avec Copybara.
Notre équipe l’utilise aussi en interne pour gérer les versions d’un ensemble de règles Starlark.
Avoir un dépôt public comme dépendance d’un dépôt privé interne devient assez pénible côté développement. Quand ce genre de dépendances se met à pousser en arbre, c’est vraiment un casse-tête.
Je l’utilise depuis assez longtemps, surtout quand un outil créé au sein d’un gros projet a suffisamment pris d’ampleur pour mériter une publication indépendante.
C’est assez puissant pour gérer toute la distribution bidirectionnelle, exporter le code puis le réimporter, mais c’est tellement pénible que je m’en passe.
Je m’en sers généralement pour un simple export ponctuel : détacher un dossier du dépôt d’origine tout en conservant l’historique. Ensuite, le développement passe dans le nouveau dépôt.
Même si la nouvelle structure du projet est complètement différente,
Git blamefonctionne, donc ça me convient.Le bidirectionnel devient vite sale, parce que des transformations comme le remappage de chemins, l’exclusion de fichiers ou la suppression d’en-têtes sont faciles dans un sens, mais ne peuvent pas toujours être inversées proprement.
Quand les deux côtés divergent, le suivi de la ligne de base de Copybara commence à produire des résultats confus. Même des commits sémantiquement identiques produisent des SHA différents après transformation.
À savoir : la « conservation » de l’historique n’est pas une vraie transplantation, mais consiste à cherry-picker des commits réécrits. Le contenu des fichiers et les informations d’auteur sont transférés, donc
Git blamefonctionne, mais les SHA sont nouveaux.Copybara place le SHA d’origine dans le trailer de message de commit
GitOrigin-RevId, ce qui est pratique si l’on doit plus tard faire correspondre des commits entre dépôts.Plus de 52 ans de progrès, donc :-)
Juillet 2026 : Google copybara permet de déplacer du code entre deux dépôts de production.
Mars 1974 : IBM COPY permettait de déplacer du code entre deux jeux de données partitionnés de production. OS/MVT et OS/VS2 TSO Data Utilities COPY, FORMAT, LIST, MERGE User's Guide and Reference https://www.computinghistory.org.uk/downloads/8987
Chez Dagster, nous avons utilisé Copybara pour mettre en place un modèle hub-and-spoke permettant au dépôt public de vivre à l’intérieur d’un monorepo interne plus vaste ; ça a fonctionné, mais il a fallu pas mal de contournements.
https://dagster.io/blog/monorepos-the-hub-and-spoke-model-an...
Si l’on a seulement besoin de synchroniser des dépôts, sans exclusions ni transformations, je ne pense pas que je l’utiliserais. Ça peut convenir aujourd’hui, mais si l’outil est archivé ou abandonné, comme kaniko ou beaucoup de produits/outils Google, ça peut devenir problématique.
GitLab offre une méthode très simple pour faire du miroir depuis GitLab vers GitHub ou d’autres fournisseurs/serveurs Git.
Par exemple, convertir des fichiers
bzlexternes vers un format compatible avec lesBUILDBlaze internes, ou passer d’imports externes à des imports internes de typethird_party, et inversement.Pour un pur miroir, Copybara est beaucoup trop lourd.
Bien. Il y a environ 5 ans, j’avais moi aussi bricolé quelque chose de similaire avec des dépôts Git imbriqués et des scripts, afin de gérer à la fois des dépôts privés et publics.
Mes scripts shell n’étaient évidemment pas à l’échelle de Google.
git subtree, mais à y regarder, ça semble faire beaucoup plus de choses.Par exemple, il y a aussi une fonction pour changer l’adresse e-mail de l’auteur du commit pendant la synchronisation.