Close

Dependências do Git e do projeto

Foto profissional de Nicola Paolucci
Nicola Paolucci

Representante do desenvolvedor

Imagine as seguintes questões. Como você lida com as dependências do projeto com o git? O projeto é composto por vários repositórios interdependentes. No momento, eles são gerenciados com svn:externals. Qual é a melhor maneira de lidar com esse caso com o git? Como você divide um repositório muito grande em componentes menores usando o git? Estes são alguns exemplos das perguntas mais frequentes que a gente recebeu na etapa europeia do tour Getting Git Right.

O tópico parece ser um grande problema para muitas equipes de software que adotam o git; portanto, neste artigo, vou tentar esclarecer o problema.

É óbvio que, as dependências do projeto e a infraestrutura de build são duas áreas interligadas e, mesmo dentro da Atlassian, foi iniciada uma discussão sobre o "Futuro dos builds".

Ter repositórios separados em vez de ter um único pode tornar algumas coisas mais difíceis. Mas é um passo natural em comparação e — às vezes obrigatório — na evolução de um projeto de software por pelo menos dois motivos principais: aumento dos tempos de compilação e compartilhamento de dependências entre projetos.

Imagine as seguintes questões. Como você lida com as dependências do projeto com o git? O projeto é composto por vários repositórios interdependentes. No momento, eles são gerenciados com svn:externals. Qual é a melhor maneira de lidar com esse caso com o git? Como você divide um repositório muito grande em componentes menores usando o git? Estes são alguns exemplos das perguntas mais frequentes que a gente recebeu na etapa europeia do tour Getting Git Right.

O tópico parece ser um grande problema para muitas equipes de software que adotam o git; portanto, neste artigo, vou tentar esclarecer o problema.

É óbvio que, as dependências do projeto e a infraestrutura de build são duas áreas interligadas e, mesmo dentro da Atlassian, foi iniciada uma discussão sobre o "Futuro dos builds".

Ter repositórios separados em vez de ter um único pode tornar algumas coisas mais difíceis. Mas é um passo natural em comparação e — às vezes obrigatório — na evolução de um projeto de software por pelo menos dois motivos principais: aumento dos tempos de compilação e compartilhamento de dependências entre projetos.


Pintura com traços amplos: diretrizes e soluções abaixo do ideal


Então, voltando à pergunta: Como você rastreia e gerencia as dependências do projeto com o git?

Se for possível, não faça!

Brincadeiras à parte, deixe-me responder com traços amplos primeiro e ir mais fundo depois. Perceba que não há nenhuma bala de prata — no git ou não — que vai resolver sem problemas todos os problemas relacionados às dependências do projeto.

Depois que um projeto cresce em um determinado tamanho, faz sentido que ele seja dividido em componentes lógicos, mas não espere ter mais de 100 milhões de linhas de código em um único repositório antes de fazer essa divisão. Portanto, a seguir estão apenas diretrizes para que você possa criar sua própria abordagem.

Logotipo do Git
Material relacionado

Instalar o Git

Logotipo do Bitbucket
VER SOLUÇÃO

Aprenda a usar o Git com o Bitbucket Cloud

Primeira opção: use uma ferramenta de compilação/dependência apropriada em vez do git


Uma ferramenta de gerenciamento de dependências é o meu caminho atual recomendado para lidar com as dores de crescimento e os tempos de compilação de projetos consideráveis.

Mantenha seus módulos separados em repositórios individuais e gerencie a interdependência usando uma ferramenta criada para o trabalho. Existe um para (quase) todas as pilhas de tecnologia existentes. Alguns exemplos:

  • Maven (ou Gradle) se você usar Java
  • npm para aplicativos de ponto central
  • Bower, Component.io, etc. se você usa Javascript (atualizado!)
  • Pip e requirements.txt se você usa Python
  • RubyGems,Bundler se você usa Ruby
  • NuGet para.NET
  • Ivy (ou alguma ação personalizada do CMake) para C++ (atualizado!)
  • Aplicativos CocoaPods para Cocoa iOS
  • Composer ou Phing para PHP (adicionado!)
  • Em Go, a infraestrutura de build/dependência é um pouco incorporada à linguagem (embora as pessoas estejam trabalhando em uma solução mais completa, veja godep). Para o servidor Git Bitbucket Server, usamos o Maven e o Bower. No momento da compilação, a ferramenta escolhida vai extrair as versões corretas das dependências para que seu projeto principal possa ser compilado. Algumas dessas ferramentas têm limitações e fazem suposições que não são ideais, mas são comprovadas e viáveis.

As dificuldades de dividir o projeto

No início de um projeto, a estrutura é simples, tudo é embalado em um único build. Mas, à medida que o projeto cresce, essa simplicidade pode resultar em seu build muito lento — nesse ponto você precisa de armazenamento em "cache," que é onde o gerenciamento de dependências entra em ação. Aliás, essa informação indica que os submódulos (veja abaixo) se prestam muito bem a linguagens dinâmicas, por exemplo. Em resumo, acho que a maioria das pessoas precisa se preocupar com os tempos de compilação em algum momento, e é por esse motivo que você deve usar uma ferramenta de gerenciamento de dependências.

Dividir componentes em repositórios separados traz muita dor. Em nenhuma ordem específica:

  • Fazer uma alteração em um componente requer uma versão
  • Leva tempo e pode falhar por vários motivos idiotas
  • Parece idiota para pequenas mudanças
  • Exige a configuração manual de novos builds para cada componente
  • Dificulta a capacidade de descoberta dos repositórios
  • Refatoramento quando nem toda a fonte está disponível em um único repositório
  • Em algumas configurações (como essa), a atualização de APIs requer um lançamento marco do produto e, em seguida, o plug-in e, em seguida, o produto de novo. É provável que tenhamos esquecido alguma coisa, mas você entendeu. Uma solução perfeita para o problema está longe daqui.

Segunda opção: Usar o submódulo git


Se você não pode ou não quer usar uma ferramenta de dependência, o git tem uma facilidade para lidar com submódulos. Os submódulos podem ser convenientes, em particular para linguagens dinâmicas. No entanto, eles não vão sempre salvá-lo de tempos de compilação lentos. Já escrevi algumas diretrizes e dicas sobre elas e também explorei alternativas. A Internet em geral também tem argumentos contra eles.

Correspondência 1:1 entre svn:external e git

MAS! Se você está procurando uma correspondência 1-para-1 entre svn:externals e git, você precisa usar submódulos garantindo que os submódulos rastreiem apenas branches de lançamento e não commits aleatórios.

Terceira opção: usar outras ferramentas de dependência de build e pilha cruzada


Nem sempre você vai desfrutar de um projeto uniforme no total e que pode ser construído e montado com uma única ferramenta. Por exemplo, alguns projetos móveis vão precisar manipular as dependências Java e C++ ou usar ferramentas proprietárias para gerar ativos. Para essas situações mais complexas, você pode aprimorar o git com uma camada extra no topo. Um ótimo exemplo nessa área é o repositório do Android.

Outras ferramentas de build que valem a pena explorar:

Conclusões e leituras adicionais


Leituras adicionais sobre o tópico de infraestrutura de build (e Maven) foram sugeridas com cuidado por Charles O'Farrell, um combustível muito interessante para reflexão:

Gostaria de concluir com esta excelente citação do último artigo acima. Mesmo que seja sobre o Maven, ele também pode ser aplicado a outras ferramentas de build e dependência:

"Um cache não faz nada além de acelerar as coisas. Você poderia remover um cache por completo e o sistema circundante funcionaria da mesma forma, apenas com mais lentidão. Um cache também não tem efeitos colaterais. Não importa o que você tenha feito com um cache no passado, uma determinada consulta ao cache vai devolver o mesmo valor para a mesma consulta no futuro.

A experiência do Maven é muito diferente do que eu descrevo! Os repositórios Maven são usados como caches, mas sem ter as propriedades dos caches. Quando você pede algo de um repositório Maven, é muito importante o que você fez no passado. Ele retorna a coisa mais recente que você colocou nele. Pode até falhar, se você pedir algo antes de colocar."

Nicola Paolucci

Nicola is an all-round hacker who loves exploring and teaching bleeding edge technologies. He writes and talks about Git, development workflows, code collaboration and more recently about Docker. Prior to his current role as Developer Instigator at Atlassian he led software teams, built crowd sourcing applications for geo-spacial data, worked on huge e-commerce deployments. Little known facts about Nicola: he gesticulates a lot while speaking (being Italian), lives in Amsterdam and rides a Ducati.


Compartilhar este artigo

Leitura recomendada

Marque esses recursos para aprender sobre os tipos de equipes de DevOps ou para obter atualizações contínuas sobre DevOps na Atlassian.

Pessoas colaborando usando uma parede cheia de ferramentas

Blog do Bitbucket

Ilustração do DevOps

Caminho de aprendizagem de DevOps

Demonstrações de funções no Demo Den com parceiros da Atlassian

Como o Bitbucket Cloud funciona com o Atlassian Open DevOps

Inscreva-se para receber a newsletter de DevOps

Thank you for signing up