Organizando repositórios Git com sub-módulos aninhados comuns

48

Sou um grande fã dos sub-módulos do Git . Eu gosto de poder rastrear uma dependência junto com sua versão, para que você possa reverter para uma versão anterior do seu projeto e ter a versão correspondente da dependência para construir de maneira segura e limpa. Além disso, é mais fácil liberar nossas bibliotecas como projetos de código aberto, já que o histórico das bibliotecas é separado daquele das aplicações que dependem delas (e que não terão origem aberta).

Estou configurando o fluxo de trabalho para vários projetos no trabalho, e fiquei me perguntando como seria se considerássemos essa abordagem um pouco extrema em vez de ter um único projeto monolítico. Eu rapidamente percebi que existe uma potencial lata de worms em realmente usando sub-módulos.

Suponha um par de aplicativos: studio e player e bibliotecas dependentes core , graph e network , onde dependências são as seguintes:

  • core é autônomo
  • graph depende de core (sub-módulo em ./libs/core )
  • network depende de core (sub-módulo em ./libs/core )
  • studio depende de graph e network (sub-módulos em ./libs/graph e ./libs/network )
  • player depende de graph e network (sub-módulos em ./libs/graph e ./libs/network )

Suponha que estamos usando o CMake e que cada um desses projetos tenha testes de unidade e todos os trabalhos. Cada projeto (incluindo studio e player ) deve ser capaz de ser compilado de forma independente para executar métricas de código, testes unitários, etc.

A coisa é, um git submodule fetch recursivo, então você obtém a seguinte estrutura de diretórios:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/         (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/       (sub-module depth: 2)
studio/libs/network/libs/core/

Observe que core é clonado duas vezes no projeto studio . Além desse desperdício de espaço em disco, tenho um problema no sistema de compilação porque estou criando core duas vezes e posso obter duas versões diferentes de core .

Pergunta

Como organizo submódulos para que eu obtenha a dependência com versão e a construção autônoma sem obter várias cópias de sub-módulos aninhados comuns?

Possível solução

Se a dependência da biblioteca for de alguma forma uma sugestão (isto é, uma moda conhecida como "trabalhar X versão X" ou "somente a versão X é oficialmente suportada") e bibliotecas ou aplicativos dependentes potenciais são responsáveis por construir com qualquer versão como, então eu poderia imaginar o seguinte cenário:

  • Ter o sistema de compilação para graph e network informando onde encontrar core (por exemplo, por meio de um caminho de inclusão do compilador). Defina dois destinos de construção, "autônomo" e "dependência", em que "autônomo" seja baseado em "dependência" e inclua o caminho de inclusão para apontar para o sub-módulo core local.
  • Introduza uma dependência extra: studio on core . Em seguida, studio constrói core , define o caminho de inclusão para sua própria cópia do submódulo core e, em seguida, constrói graph e network no modo "dependência".

A estrutura de pastas resultante se parece com:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/         (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/       (empty folder, sub-modules not fetched)

No entanto, isso requer alguma mágica de sistema de compilação (estou bastante confiante de que isso pode ser feito com o CMake) e um pouco de trabalho manual por parte das atualizações de versão (atualizar graph também pode exigir atualização core e network para obter uma versão compatível de core em todos os projetos).

Alguma opinião sobre isso?

    
por André Caron 17.10.2011 / 17:37
fonte

5 respostas

5

Estou muito atrasado para esta festa, mas a sua pergunta ainda não parece ter uma resposta completa, e é um hit bastante proeminente do Google.

Eu tenho exatamente o mesmo problema com C ++ / CMake / Git / Submodules e eu tenho um problema similar com o MATLAB / Git / Submodules, o que causa estranheza extra porque o MATLAB não é compilado. Eu me deparei com este vídeo recentemente, que parece propor uma "solução". Não gosto da solução, porque essencialmente significa jogar fora os submódulos, mas elimina o problema. É exatamente como o @errordeveloper recomenda. Cada projeto não possui submódulos. Para construir um projeto, crie um superprojeto para construí-lo e inclua-o como um irmão para suas dependências.

Assim, seu projeto para desenvolver graph pode parecer:

buildgraph/graph
buildgraph/core

e depois o seu projeto para estúdio poderia ser:

buildstudio/studio
buildstudio/graph
buildstudio/network
buildstudio/core

Os superprojetos são apenas um CMakeLists.txt principal e vários submódulos. Mas nenhum dos projetos tem nenhum submódulo.

O único custo que vejo para essa abordagem é a proliferação de "super-projetos" triviais que são dedicados apenas à construção de seus projetos reais. E se alguém se apossar de um de seus projetos, não há uma maneira fácil de descobrir sem encontrar o superprojeto, quais são suas dependências. Isso pode fazer com que fique muito feio no Github, por exemplo.

    
por 28.07.2016 / 15:18
fonte
1

Suponho que, ao integrar os submodules graph e network em studio , você sempre deve ter a mesma versão de core em um determinado momento no histórico de studio . Gostaria de simular o submódulo studio/libs/core em studio/libs/{graph,network}/libs .

Atualização:

Eu criei vários repositórios com as dependências que você declarou:

./core      <--- (v2)
./graph
./graph/libs
./graph/libs/core  <--- (v2)
./graph/.gitmodules
./network
./network/libs
./network/libs/core  <--- (v1)
./network/.gitmodules
./studio
./studio/libs
./studio/libs/graph
./studio/libs/graph/libs
./studio/libs/graph/libs/core <--- (v1)
./studio/libs/graph/.gitmodules
./studio/libs/network
./studio/libs/network/libs
./studio/libs/network/libs/core  <--- (v1)
./studio/libs/network/.gitmodules
./studio/studio
./studio/.gitmodules

v1 e v2 são duas versões diferentes de core . graph manipula a versão 2, enquanto network precisa de algum trabalho e está preso na versão 1. Em studio , as versões incorporadas locais de core apontam para v1 para ter um programa em funcionamento. Agora, além da perspectiva de construção, tudo funciona bem com submódulos.

Agora posso remover o seguinte diretório:

./studio/libs/network/libs/core

E substitua-o por um link simbólico:

./studio/libs/network/libs/[email protected] -> ../../graph/libs/core/

Eu confirmo localmente essa alteração e perco a capacidade de ter duas versões separadas de core dentro de studio , mas só construo core uma vez. Quando estou pronto para atualizar para v2 , posso fazer:

 git submodule update # (--rebase ?)

... dentro do studio / libs / network.

    
por 10.11.2011 / 22:11
fonte
0

Eu iria achatar a profundidade do sub-módulo de apenas um e ter um repositório que manteria todos os módulos como sub-módulos e nada mais além do README e dos scripts de compilação. Haveria um script de construção separado para cada um dos pacotes que ligam suas dependências. Caso contrário, você pode ter um repositório separado para um pacote.

    
por 17.10.2011 / 22:34
fonte
0

Eu não usaria submódulos.

É tentador, como costumava ser o caso com o svn-externals. No entanto, você pode ter certeza de que todos esses projetos vinculados ainda estão no mesmo lugar em um ano? E quanto em cinco?

Portanto, estou simplesmente copiando todas as dependências necessárias para o meu projeto. Isso significa que, contanto que meu repo seja válido, posso verificar o estado exato.

Basicamente, tenho uma estrutura de pastas da seguinte forma:

myproject/... [sources etc]
ext/ [third-party dependencies]


e.g. ext/boost, ext/cppunit

Embora isso não seja muito bom do ponto de vista do espaço em disco, eu valorizo a garantia de que posso verificar todos os estados gravados, desde que o repositório esteja disponível muito mais alto.

Além disso, há vários problemas com submódulos, conforme descrito aqui

    
por 30.04.2013 / 14:08
fonte
0

Enfrentando exatamente o mesmo problema aqui. Uma das soluções poderia ser ter algum repo libs que tivesse core , network , graph como submódulos e apenas CMakeLists que informasse a cada uma das bibliotecas onde encontrar suas dependências. Cada aplicação agora teria libs como submódulo e usaria apenas as bibliotecas necessárias.

O teste de cada lib pode ser configurado de duas maneiras:

  • Tenha o core_testing, o graph_testing, o network_testing como aplicativos separados
  • Implante libs testadas em servidores de teste e encontre-as enquanto executa testes usando cmake
por 24.12.2015 / 15:54
fonte