1 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Copybara es una herramienta usada internamente en Google para transformar y mover código fuente entre varios repositorios, en casos como sincronizar repositorios confidential y public.
  • Permite elegir un repositorio como repositorio autoritativo para mantener una única fuente de verdad, pero se pueden recibir contribuciones desde cualquier repositorio y crear releases desde cualquiera de ellos.
  • Su caso de uso principal es el movimiento repetitivo de código, con flujos para traer parte del código desde un repositorio confidential a uno public, o para incorporar cambios de un repositorio public al repositorio authoritative.
  • Copybara usa un enfoque stateless: guarda el estado en labels de mensajes de commit del repositorio de destino, no en un servidor aparte, por lo que varios usuarios o servicios pueden obtener el mismo resultado con la misma configuración y repositorios.
  • El tipo de repositorio compatible actualmente es Git; la lectura de Mercurial es experimental, y su arquitectura extensible permite agregar origins y destinations personalizados.

El problema que resuelve Copybara

  • Copybara es una herramienta para mover y transformar código fuente entre repositorios.
  • Hay casos en los que el código fuente debe existir en varios repositorios, y Copybara permite transformarlo y moverlo entre ellos.
  • Un caso representativo es un proyecto que mantiene sincronizados un repositorio confidential y un repositorio public.
  • La forma de uso más común es mover código repetidamente de un repositorio a otro.
  • También puede usarse para mover código una sola vez a un repositorio nuevo.

Repositorio autoritativo y flujo de contribuciones

  • Copybara requiere elegir uno de los repositorios como authoritative repository.
    • Es una condición para que siempre exista una única source of truth.
  • Las contribuciones pueden hacerse desde cualquier repositorio.
  • Los releases también pueden crearse desde cualquier repositorio.
  • Si ocurre un cambio en un repositorio no autoritativo, Copybara puede transformar ese cambio y moverlo a la ubicación adecuada en el repositorio autoritativo.
    • Un ejemplo es un cambio hecho por un contributor en un repositorio public.
    • Los conflictos de merge se manejan de la misma forma que los cambios obsoletos dentro del repositorio autoritativo.

Ejemplos de uso

  • Los ejemplos de uso de Copybara incluyen:
    • traer parte del código de un repositorio confidential a un repositorio public;
    • traer código de un repositorio public a un repositorio confidential;
    • traer cambios de un repositorio non-authoritative al repositorio authoritative.
  • La configuración de ejemplo define el origin y el destination con core.workflow.
    • El origin usa git.github_origin con master de https://github.com/google/copybara.git.
    • El destination usa git.destination con file:///tmp/foo.
    • destination_files apunta a third_party/copybara/** y excluye README_INTERNAL.txt.
    • core.replace y core.move realizan el reemplazo de rutas del archivo BUILD y el movimiento de directorios.
  • El ejemplo de ejecución consiste en crear un repositorio Git bare y luego ejecutar copybara copy.bara.sky.

Forma de guardar estado y soporte de repositorios

  • Una de las características principales de Copybara es su estructura stateless.
  • Más exactamente, guarda el estado en el repositorio de destino.
    • La ubicación donde se guarda son los labels del mensaje de commit.
  • Con este enfoque, varios usuarios o servicios pueden obtener el mismo resultado usando la misma combinación de configuración y repositorios.
  • El tipo de repositorio compatible actualmente es Git.
  • Es posible leer desde repositorios Mercurial, pero todavía es experimental.
  • Gracias a una arquitectura extensible, se pueden agregar origins y destinations bespoke para casi cualquier caso de uso.
  • El soporte oficial para otros tipos de repositorios se agregará en el futuro.

Instalación y build

  • La forma más sencilla de empezar es usar un snapshot release semanal que incluye binarios precompilados.
  • Para usar una versión no publicada, hay que hacer el build desde HEAD.
    • Se requiere instalar JDK 11.
    • Se requiere instalar Bazel.
    • Clonar el código fuente con git clone https://github.com/google/copybara.git.
    • Hacer el build con bazel build //java/com/google/copybara.
    • El uberjar ejecutable se genera con bazel build //java/com/google/copybara:copybara_deploy.jar.
    • Las pruebas pueden ejecutarse con bazel test //....
  • Algunas pruebas requieren herramientas base como Mercurial o Quilt.
    • Si el Pull Request no está relacionado con ese módulo, se pueden omitir esas pruebas.
    • CI ejecuta todas las pruebas.
  • En Arch Linux se puede usar el paquete aur/copybara-git.

Usar Copybara precompilado en Bazel

  • Se puede usar el snapshot release semanal en Bazel.
  • Copybara se distribuye con class file version 65.0, por lo que debe ejecutarse con Java Runtime 21 o superior.
    • Es necesario agregar run --java_runtime_version=remotejdk_21 a .bazelrc.
  • El artifact de release se descarga con http_jar.
    • En WORKSPACE, usar load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar").
    • En MODULE.bazel, usar http_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar").
  • En WORKSPACE o MODULE.bazel, completar el lugar de [version] para especificar copybara_deploy.jar.
  • En el archivo BUILD, declarar java_binary y usar com.google.copybara.Main como main class.
  • Un ejemplo de ejecución es bazel run //tools:copybara -- migrate copy.bara.sky.

Build desde código fuente como repositorio Bazel externo

  • Se proporciona una macro de conveniencia para las dependencias de Copybara.
  • Agregar http_archive a WORKSPACE y completar los valores {{ sha256sum }} y {{ commit }}.
  • Luego cargar y llamar las siguientes macros:
    • copybara_repositories()
    • copybara_maven_repositories()
    • copybara_go_repositories()
  • Dentro del workspace, se puede hacer el build y ejecutar con bazel run @com_github_google_copybara//java/com/google/copybara -- <args...>.

Uso con Docker

  • La forma de compilar y ejecutar Copybara con Docker actualmente es experimental.
  • El build se hace con docker build --rm -t copybara ..
  • La ejecución se hace desde la raíz del código de destino con algo como docker run -it -v "$(pwd)":/usr/src/app copybara help.
  • En lugar de argumentos al ejecutar el contenedor, se pueden usar variables de entorno.
    • COPYBARA_SUBCOMMAND=migrate: cambia el comando de ejecución; el valor predeterminado es migrate.
    • COPYBARA_CONFIG=copy.bara.sky: especifica la ruta del archivo de configuración; el valor predeterminado es copy.bara.sky en la raíz.
    • COPYBARA_WORKFLOW=default: especifica el workflow a ejecutar; el valor predeterminado es default.
    • COPYBARA_SOURCEREF='': especifica sourceref; no hay valor predeterminado.
    • COPYBARA_OPTIONS='': especifica opciones de Copybara; no hay valor predeterminado.
  • La configuración de Git y las credenciales SSH pueden compartirse con el contenedor Docker.
    • El ejemplo consiste en montar ~/.gitconfig, ~/.ssh y SSH_AUTH_SOCK en el contenedor.

Documentación y consultas

1 comentarios

 
GN⁺ 4 시간 전
Opiniones de Hacker News
  • Me pareció curioso que este artículo saliera justo después de que yo publicara como open source un parche con soporte para Perforce que hice para usarlo en un estudio de desarrollo de videojuegos.
    Considerando que el uso principal de Copybara es distribuir código interno de Google, y que ese código está en Piper, que está relacionado con Perforce, me sorprendió bastante que no tuviera soporte para Perforce y que solo el soporte para Git fuera realmente significativo.
    Antes de crear el PR, al revisar el historial de Git vi muchas marcas de Gerrit Change-ID, así que también me preocupó que existiera en algún lado un sistema de revisión de código Gerrit al que no tengo acceso y que mi PR no llegara a upstream.
    También es una lástima que no exista Gerrit/Rietveld para Perforce, pero no se puede tener todo.
    https://github.com/google/copybara/pull/347

    • Una de las razones por las que Gerrit/Rietveld no tiene soporte para Perforce es que Google no usa esas herramientas para los cambios de código almacenados en Piper. En su lugar usa Critique.
      https://abseil.io/resources/swe-book/html/ch19.html
      https://read.engineerscodex.com/p/how-google-takes-the-pain-...
      Todavía no he encontrado entre las herramientas externas algo tan bueno como Critique, y me sorprende que las pobres herramientas de revisión de PR de GitHub sean aceptables para la mayoría. Si alguien conoce una herramienta de nivel similar, me gustaría saberlo.
      Hace unos años, cuando me fui de Google, busqué con bastante detalle y https://codeapprove.com/ era lo más cercano, pero todavía le faltaban muchas cosas.
    • Piper no es un fork de Perforce. Es compatible con la API de Perforce, pero es una implementación completamente distinta.
    • Ese repositorio sí acepta PR. Solo que los fusionan internamente y luego los vuelven a exportar hacia afuera.
      Los proyectos open source como gVisor o Bazel, que viven en el monorepo interno, se manejan de forma parecida en general, aunque con pequeñas diferencias.
  • Otra herramienta interesante en esta área es Josh, que Rust usa para sincronizar commits.
    https://josh-project.dev
    También hay una entrada del blog del lado de Rust.
    https://blog.rust-lang.org/inside-rust/2026/06/04/how-josh-h...
    Meta antes tenía una herramienta open source llamada fbshipit, pero según el repositorio público ya no la usan.
    https://github.com/facebookarchive/fbshipit
    ¿Habrá otras herramientas en este campo?

  • ¿Esto también es práctico cuando varios repositorios quieren compartir un poco de código, pero no vale la pena separarlo como biblioteca, referenciarlo, publicar releases de versiones y actualizar los repositorios dependientes?
    Por ejemplo, me pregunto si podría usarse para simplemente sincronizar una carpeta con modelos de dominio comunes desde un repositorio principal hacia otros repositorios.
    Es un uso cercano a la filosofía estilo Go de “mejor copiar un poco que tener un montón de dependencias”.

    • Se usa principalmente para sincronizar proyectos open source externos con el monorepo interno. Por política se exige importar código fuente en vez de artefactos de build, aunque se pueden obtener excepciones.
      Algunos proyectos se desarrollan en el monorepo y se exportan hacia afuera con Copybara.
      Nuestro equipo también lo usa internamente para el versionado de un conjunto de reglas de Starlark.
    • Es una herramienta para cuando internamente tienes un monorepo y quieres publicar como open source parte de él al mundo. Aun así, el código debe seguir dentro del monorepo, así que esta es la solución.
      Si pones el repositorio público como dependencia de un repositorio privado interno, desde el punto de vista del desarrollo se vuelve bastante complicado. Si esas dependencias crecen como un árbol, sí que se convierte en un dolor de cabeza.
    • Con Copybara se puede hacer algo así, pero si lo usas de esa forma probablemente resulte molesto y tedioso. Puede terminar siendo más engorroso que separar una biblioteca o empujar unos cuantos archivos a un repositorio aparte.
  • Lo he usado durante bastante tiempo, principalmente cuando una herramienta creada dentro de un proyecto grande creció lo suficiente como para ameritar un lanzamiento independiente.
    Es lo bastante potente como para manejar toda una distribución bidireccional de exportar código y volver a importarlo, pero eso es demasiado engorroso, así que paso.
    Yo lo uso más que nada para exportaciones simples de una sola vez, separando una carpeta del repositorio original pero conservando el historial. Después, el desarrollo se mueve al nuevo repositorio.
    Me basta con que Git blame funcione aunque la estructura del nuevo proyecto sea completamente distinta.

    • Ese patrón unidireccional es, de hecho, la forma en que también se usa internamente en Google. Sincronizan hacia afuera desde el monorepo hacia GitHub.
      Lo bidireccional se vuelve desordenado, porque transformaciones como remapeo de rutas, exclusión de archivos o eliminación de encabezados son fáciles en una dirección, pero no siempre se pueden invertir limpiamente.
      Si ambos lados divergen, el seguimiento de línea base de Copybara empieza a producir resultados confusos, porque incluso commits semánticamente iguales generan SHA distintos después de la transformación.
      Algo que vale la pena saber es que la “preservación” del historial no es una portación real, sino que funciona haciendo cherry-pick de commits reescritos. Como pasan el contenido de los archivos y la información de autor, Git blame funciona, pero los SHA son nuevos.
      Copybara guarda el SHA original en el tráiler de mensaje de commit GitOrigin-RevId, lo cual es útil si más adelante hay que comparar commits entre repositorios.
  • Más de 52 años de progreso :-)
    Julio de 2026: Google copybara permite mover código entre dos repositorios de producción.
    Marzo de 1974: IBM COPY permitía mover código entre dos conjuntos de datos particionados de producción. OS/MVT y OS/VS2 TSO Data Utilities COPY, FORMAT, LIST, MERGE User's Guide and Reference https://www.computinghistory.org.uk/downloads/8987

  • En Dagster usamos Copybara para armar un modelo hub-and-spoke que permitiera que los repositorios públicos vivieran dentro de un monorepo interno más grande, y funcionó, aunque requirió bastantes rodeos.
    https://dagster.io/blog/monorepos-the-hub-and-spoke-model-an...

  • Si solo necesitas sincronizar repositorios, sin exclusiones ni transformaciones, creo que no lo usaría. Puede encajar por ahora, pero si termina archivado o discontinuado como kaniko o muchos productos/herramientas de Google, podrías quedar en problemas.
    GitLab tiene una forma muy simple de hacer mirroring desde GitLab hacia GitHub u otros proveedores/servidores Git.

    • Creo que es realmente poco probable que Copybara sea discontinuado. Hasta donde sé, es una herramienta clave en la forma en que se mantiene y vendoriza google3 con grandes proyectos de código abierto.
    • Exacto, Copybara es más bien una herramienta para hacer transformaciones en una dirección o en ambas.
      Por ejemplo, convertir bzl externos a un formato compatible con BUILD de Blaze interno, o cambiar entre imports externos e imports internos al estilo third_party.
      Para un mirror puro, Copybara es demasiado pesado.
  • Bien. Yo también armé algo parecido hace unos 5 años con repositorios Git anidados y scripts para poder manejar juntos repositorios privados y públicos.
    Mis scripts de shell, obviamente, no estaban a escala Google.

    • A mí me pasó algo similar. Al principio pensé que sería un wrapper de git subtree, pero al verlo parece que hace mucho más.
      Por ejemplo, también tiene una función para cambiar el correo electrónico del autor del commit durante la sincronización.