Google Copybara: movimentação de código entre repositórios
(github.com/google)- Copybara é uma ferramenta usada internamente no Google para transformar e mover código-fonte entre vários repositórios, em casos como a sincronização entre repositórios confidential e public
- Ao escolher um repositório como repositório autoritativo, mantém-se uma única fonte da verdade, mas contribuições podem ser recebidas de qualquer repositório e releases também podem ser criadas a partir de qualquer repositório
- O principal caso de uso é a movimentação repetitiva de código, com suporte a fluxos como levar parte do código de um repositório confidential para um repositório public ou trazer mudanças de um repositório public para o repositório autoritativo
- O Copybara usa uma abordagem stateless que armazena o estado não em um servidor separado, mas em labels nas mensagens de commit do repositório de destino, permitindo que vários usuários ou serviços obtenham o mesmo resultado com a mesma configuração e os mesmos repositórios
- O tipo de repositório atualmente suportado é Git; a leitura de Mercurial é um recurso experimental, e a arquitetura extensível permite adicionar origins e destinations personalizados
O problema que o Copybara resolve
- Copybara é uma ferramenta para movimentação e transformação de código-fonte entre repositórios
- Há casos em que o código-fonte precisa existir em vários repositórios, e o Copybara permite transformar e mover código entre esses repositórios
- Um caso representativo é um projeto que mantém sincronizados um repositório confidential e um repositório public
- A forma mais comum de uso é mover código repetidamente de um repositório para outro
- Também pode ser usado para mover código uma única vez para um novo repositório
Repositório autoritativo e fluxo de contribuições
- O Copybara exige que um dos repositórios seja escolhido como authoritative repository
- Essa condição existe para que sempre haja uma única source of truth
- Contribuições podem ser feitas em qualquer repositório
- Releases também podem ser criadas a partir de qualquer repositório
- Quando uma mudança ocorre em um repositório não autoritativo, o Copybara pode transformá-la e movê-la para o local apropriado no repositório autoritativo
- Um exemplo é uma mudança feita por um contributor em um repositório public
- Conflitos de merge são tratados da mesma forma que mudanças antigas dentro do repositório autoritativo
Exemplos de uso
- Exemplos de uso do Copybara incluem
- Levar parte do código de um repositório confidential para um repositório public
- Trazer código de um repositório public para um repositório confidential
- Trazer mudanças de um repositório non-authoritative para um repositório authoritative
- A configuração de exemplo define origin e destination com
core.workflow- O origin usa
git.github_origincom omasterdehttps://github.com/google/copybara.git - O destination usa
git.destinationcomfile:///tmp/foo destination_filesmirathird_party/copybara/**e excluiREADME_INTERNAL.txtcore.replaceecore.moverealizam a substituição de caminho de arquivos BUILD e a movimentação de diretórios
- O origin usa
- O exemplo de execução consiste em criar um repositório Git bare e depois executar
copybara copy.bara.sky
Forma de armazenamento de estado e suporte a repositórios
- Uma das principais características do Copybara é sua arquitetura stateless
- Mais precisamente, o estado é armazenado no repositório de destino
- O local de armazenamento são os labels nas mensagens de commit
- Com essa abordagem, vários usuários ou serviços podem obter o mesmo resultado usando a mesma combinação de configuração e repositórios
- O tipo de repositório atualmente suportado é Git
- A funcionalidade de leitura a partir de repositórios Mercurial é possível, mas ainda é experimental
- Por meio de uma arquitetura extensível, é possível adicionar origins e destinations bespoke para praticamente qualquer caso de uso
- O suporte oficial a outros tipos de repositório será adicionado no futuro
Instalação e build
- A forma mais fácil de começar é usar uma snapshot release semanal com binários pré-compilados
- As releases são geradas automaticamente
- Não há garantia de testes manuais, compatibilidade de versões ou correção
- As releases podem ser escolhidas em
https://github.com/google/copybara/releases
- Para usar uma versão ainda não lançada, é necessário fazer o build a partir do HEAD
- É necessário instalar o JDK 11
- É necessário instalar o Bazel
- Clonar o código-fonte com
git clone https://github.com/google/copybara.git - Fazer o build com
bazel build //java/com/google/copybara - O uberjar executável é gerado com
bazel build //java/com/google/copybara:copybara_deploy.jar - Os testes podem ser executados com
bazel test //...
- Alguns testes exigem a instalação de ferramentas subjacentes como Mercurial e Quilt
- Se o Pull Request não estiver relacionado a esses módulos, esses testes podem ser ignorados
- O CI executa todos os testes
- No Arch Linux, é possível usar o pacote
aur/copybara-git
Uso do Copybara pré-compilado no Bazel
- A snapshot release semanal pode ser usada no Bazel
- Como o Copybara é fornecido com class file version 65.0, ele deve ser executado em Java Runtime 21 ou superior
- É necessário adicionar
run --java_runtime_version=remotejdk_21ao.bazelrc
- É necessário adicionar
- Baixe o artefato da release com
http_jar- Em
WORKSPACE, useload("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar") - Em
MODULE.bazel, usehttp_jar = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_jar")
- Em
- Em
WORKSPACEouMODULE.bazel, preencha o campo[version]para especificarcopybara_deploy.jar - No arquivo BUILD, declare um
java_binaryusandocom.google.copybara.Maincomo main class - Um exemplo de execução é
bazel run //tools:copybara -- migrate copy.bara.sky
Build a partir do código-fonte como repositório Bazel externo
- Um macro de conveniência para as dependências do Copybara é fornecido
- Adicione
http_archiveaoWORKSPACEe preencha os valores{{ sha256sum }}e{{ commit }} - Depois, carregue e chame os seguintes macros
copybara_repositories()copybara_maven_repositories()copybara_go_repositories()
- Dentro do workspace, é possível fazer build e executar com
bazel run @com_github_google_copybara//java/com/google/copybara -- <args...>
Uso com Docker
- Fazer build e executar o Copybara com Docker é atualmente experimental
- O build é feito com
docker build --rm -t copybara . - A execução é feita a partir da raiz do código de destino no formato
docker run -it -v "$(pwd)":/usr/src/app copybara help - É possível usar variáveis de ambiente em vez de argumentos de execução do contêiner
COPYBARA_SUBCOMMAND=migrate: altera o comando a ser executado; o padrão émigrateCOPYBARA_CONFIG=copy.bara.sky: especifica o caminho do arquivo de configuração; o padrão écopy.bara.skyna raizCOPYBARA_WORKFLOW=default: especifica o workflow a executar; o padrão édefaultCOPYBARA_SOURCEREF='': especifica o sourceref; sem padrãoCOPYBARA_OPTIONS='': especifica opções do Copybara; sem padrão
- Configurações do Git e credenciais SSH podem ser compartilhadas com o contêiner Docker
- Um exemplo é montar
~/.gitconfig,~/.ssheSSH_AUTH_SOCKno contêiner
- Um exemplo é montar
Documentação e contato
- A documentação ainda está em desenvolvimento
- Os materiais disponíveis são os seguintes
- Perguntas podem ser enviadas para a mailing list
- Para ver erros de testes do Bazel sem usar
catnos arquivos de log, é possível adicionartest --test_output=streamedao~/.bazelrc
1 comentários
Opiniões no Hacker News
Achei engraçado este post aparecer logo depois de eu ter aberto como open source um patch com suporte a Perforce que fiz para usar em um estúdio de desenvolvimento de jogos
Considerando que o principal uso do Copybara é distribuir código interno do Google, e que esse código fica no Piper, que tem relação com o Perforce, foi bem surpreendente não haver suporte a Perforce e haver, de forma significativa, apenas suporte a Git
Antes de criar o PR, olhei o histórico do Git e vi muitas marcações de Gerrit Change-ID, então também fiquei preocupado que houvesse em algum lugar um sistema de code review Gerrit ao qual eu não tenho acesso e que meu PR talvez não fosse upstreamado
Também é uma pena não haver Gerrit/Rietveld para Perforce, mas não dá para querer tudo
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-...
Ainda não encontrei uma ferramenta externa tão boa quanto o Critique, e acho surpreendente que as ferramentas fracas de revisão de PR do GitHub sejam aceitas pela maioria. Se alguém souber de uma ferramenta de nível parecido, gostaria de saber
Quando saí do Google, alguns anos atrás, procurei com bastante cuidado, e https://codeapprove.com/ foi o mais próximo que encontrei, mas ainda faltava muita coisa
Projetos open source como gVisor ou Bazel, que vivem no monorepo interno, também têm pequenas diferenças, mas em geral operam de modo parecido
Outra ferramenta interessante nessa área é que o Rust usa uma ferramenta chamada Josh para sincronização de commits
https://josh-project.dev
Também há um post no blog do Rust
https://blog.rust-lang.org/inside-rust/2026/06/04/how-josh-h...
A Meta tinha antigamente uma ferramenta open source chamada fbshipit, mas, segundo o repositório público, ela não é mais usada
https://github.com/facebookarchive/fbshipit
Será que existem outras ferramentas nesse campo?
Depois foi incorporada ao próprio Git
https://manpages.debian.org/testing/git-man/git-subtree.1.en...
https://docs.github.com/en/get-started/using-git/about-git-s...
Isso também é conveniente quando vários repositórios querem compartilhar um pouco de código, mas não vale o trabalho de separar em uma biblioteca, criar referências, publicar releases de versão e atualizar os repositórios dependentes?
Por exemplo, fico curioso se daria para usar apenas sincronizando uma pasta com modelos de domínio comuns de um repositório principal para outros repositórios
Seria um uso mais próximo da filosofia em Go de que “é melhor copiar um pouco do que ter um monte de dependências”
Alguns projetos são desenvolvidos no monorepo e exportados para fora com o Copybara
Nossa equipe também o usa internamente para versionar conjuntos de regras Starlark
Ter um repositório público como dependência de um repositório privado interno é bem problemático do ponto de vista de desenvolvimento. Quando essas dependências começam a crescer em forma de árvore, vira uma dor de cabeça de verdade
Uso há bastante tempo, principalmente quando uma ferramenta criada dentro de um projeto grande cresceu o suficiente para merecer um lançamento independente
É poderoso o bastante para fazer toda a distribuição bidirecional, exportando o código e trazendo de volta, mas isso dá trabalho demais, então prefiro evitar
Em geral, uso para uma exportação simples e pontual: separo uma pasta do repositório original, mas preservo o histórico. Depois, o desenvolvimento passa para o novo repositório
Fico satisfeito porque o
Git blamefunciona mesmo que a nova estrutura do projeto seja completamente diferenteO bidirecional fica bagunçado, porque transformações como remapeamento de caminhos, exclusão de arquivos e remoção de cabeçalhos são fáceis em uma direção, mas nem sempre dá para inverter de forma limpa
Quando os dois lados divergem, o rastreamento de linha de base do Copybara começa a produzir resultados confusos. Isso porque commits semanticamente iguais geram SHAs diferentes depois da transformação
Um ponto que vale saber é que a “preservação” do histórico não é uma migração real, mas sim um cherry-pick de commits reescritos. O conteúdo dos arquivos e as informações de autoria são transferidos, então o
Git blamefunciona, mas os SHAs são novosO Copybara coloca o SHA original no trailer de mensagem de commit
GitOrigin-RevId, o que é útil quando depois é preciso comparar commits entre repositóriosMais de 52 anos de progresso :-)
Julho de 2026: o copybara do Google permite mover código entre dois repositórios de produção
Março de 1974: o IBM COPY permitia mover código entre dois conjuntos de dados particionados de produção. OS/MVT e OS/VS2 TSO Data Utilities COPY, FORMAT, LIST, MERGE User's Guide and Reference https://www.computinghistory.org.uk/downloads/8987
Na Dagster, usamos o Copybara para configurar um modelo hub-and-spoke em que o repositório público pudesse viver dentro de um monorepo interno maior. Funcionou, mas exigiu bastante tratamento indireto
https://dagster.io/blog/monorepos-the-hub-and-spoke-model-an...
Se você só precisa sincronizar repositórios, sem exclusões nem transformações, acho que eu não usaria. Pode ser adequado no momento, mas pode virar um problema se for arquivado ou descontinuado, como o kaniko e muitos produtos/ferramentas do Google
O GitLab tem uma forma bem simples de fazer espelhamento do GitLab para o GitHub ou outros provedores/servidores Git
Por exemplo, transformar
bzlexterno em um formato compatível comBUILDdo Blaze interno, ou converter entre imports externos e imports no estilo interno dethird_partyPara um espelho puro, o Copybara é pesado demais
Legal. Eu também criei algo parecido há uns 5 anos, com repositórios Git aninhados e scripts, para lidar com repositórios privados e públicos juntos
Meu script de shell, obviamente, não era em escala Google
git subtree, mas pelo visto ele faz muito mais coisasPor exemplo, também tem um recurso para mudar o e-mail do autor do commit durante a sincronização