Submódulos: Conceito central, fluxos de trabalho e dicas

Nicola Paolucci
Nicola Paolucci
Voltar para a lista

Incluir submódulos como parte do desenvolvimento do Git permite que você inclua outros projetos em sua base de código, mantendo o histórico deles separado, mas sincronizado com o seu. É uma maneira conveniente de resolver a biblioteca do fornecedor e os problemas de dependência. Como de costume com tudo do git, a abordagem é opinativa e incentiva um pouco de estudo antes que possa ser usada com proficiência. Já existem informações boas e detalhadas sobre os submódulos, então não vou repetir o que já foi dito. O que vou fazer aqui é compartilhar algumas coisas interessantes que vão ajudar você a aproveitar ao máximo esse recurso.

Sumário

  1. Conceito central
  2. Possíveis fluxos de trabalho
  3. Dicas úteis de entrada
  4. Como trocar um submódulo git pela sua própria bifurcação
  5. Como removo um submódulo?
  6. Como faço para integrar um submódulo de volta ao meu projeto?
  7. Como ignorar mudanças nos submódulos
  8. Zona de perigo! Armadilhas ao interagir com controles remotos
  9. Conclusão

Conceito central

Primeiro, quero apresentar uma breve explicação de um conceito central sobre submódulos que vai facilitar o trabalho com eles.

Os submódulos são rastreados pelo commit exato especificado no projeto pai, não uma ramificação, uma referência ou qualquer outra referência simbólica.

Eles nunca são atualizados automaticamente quando o repositório especificado pelo submódulo é atualizado, somente quando o próprio projeto pai é atualizado. Conforme expresso com clareza no capítulo Pro Git mencionado antes:

Quando você altera e faz commit nesse subdiretório [submódulo], o superprojeto percebe que o HEAD mudou e registra o commit exato no qual você está trabalhando no momento; dessa forma, quando outros clonam este projeto, eles podem recriar o ambiente exato.

Ou, em outras palavras:

[...] os submódulos git [...] são estáticos. Muito estáticos. Você está rastreando commits específicos com submódulos git — não ramificações, nem referências; um único commit. Se você adicionar commits a um submódulo, o projeto pai não vai saber. Se você tem um monte de bifurcações de um módulo, os submódulos git não se importam. Você tem um repositório remoto e aponta para um único commit. Até você atualizar o projeto pai, nada muda.

Possíveis fluxos de trabalho

Ao lembrar esse conceito central e refletir sobre ele, você pode entender que o submódulo suporta bem alguns fluxos de trabalho e outros com uma otimização menor. Existem pelo menos três cenários em que os submódulos são uma escolha justa:

  • Quando um componente ou subprojeto está mudando muito rápido ou as próximas mudanças vão quebrar a API, você pode bloquear o código para um commit específico para sua própria segurança.

  • Quando você tem um componente que não é atualizado com muita frequência e quer rastrear este componente como uma dependência do fornecedor. É o que eu faço para meus plugins vim, por exemplo.

  • Quando você está delegando uma parte do projeto a um terceiro e quer integrar o trabalho deles em um horário ou versão específico. De novo: funciona quando as atualizações não são muito frequentes.

Créditos ao finch pelos cenários bem explicados.

Dicas úteis de entrada

A infraestrutura do submódulo é poderosa e permite a separação e integração úteis de bases de código. No entanto, existem operações simples que não têm um procedimento simplificado ou um forte suporte à interface do usuário da linha de comando.

Se você usa submódulos git em seu projeto, já os encontrou ou vai encontrar. Quando acontecer, você vai ter que procurar a solução. Várias e várias vezes. Vou economizar seu tempo de pesquisa: Instapaper, Evernote ou coloque esta página nos favoritos à moda antiga (:D:D) e você vai estar preparado por um bom tempo.

Então, aqui está o que eu tenho para você:

Como trocar um submódulo git pela sua própria bifurcação

Este é um fluxo de trabalho muito comum: você começa a usar o projeto de outra pessoa como submódulo, mas depois de um tempo encontra a necessidade de fazer personalizações e ajustes por conta própria, então quer bifurcar o projeto e substituir o submódulo por sua própria bifurcação. Mas como?

Os submódulos são armazenados em .gitmodules:

$ cat .gitmodules [submodule "ext/google-maps"] path = ext/google-maps url = git://git.naquadah.org/google-maps.git

Você pode simplesmente editar o url com um editor de texto e executar o seguinte:

$ git submodule sync

Essa ação atualiza o .git/config, que contém uma cópia desta lista de submódulos (você também pode editar a seção [submodule] relevante do .git/config manualmente).

Referência do Stack Overflow

Como removo um submódulo?

É uma necessidade bastante comum, mas tem um procedimento um pouco complexo. Para remover um submódulo, você precisa:

  1. Exclua a linha relevante do arquivo .gitmodules .
  2. Exclua a seção relevante de .git/config.
  3. Execute git rm --cached path_to_submodule (sem barra).
  4. Faça o commit e exclua os arquivos de submódulo agora não rastreados.

    Referência do Stack Overflow

Como faço para integrar um submódulo de volta ao meu projeto?

Ou, em outras palavras, como faço para desfazer o submódulo git? Se tudo o que você quer é colocar o código do submódulo no repositório principal, só precisa remover o submódulo e adicionar mais uma vez os arquivos ao repositório principal:

  1. Exclua a referência ao submódulo do índice, mas mantenha os arquivos:

    git rm --cached submodule_path (sem barras)
  2. Exclua o arquivo .gitmodules ou, se você tiver mais de um submódulo, edite este arquivo removendo o submódulo da lista:

    git rm .gitmodules
  3. Remova a pasta de metadados .git (verifique se você tem backup disso):

    rm -rf submodule_path/.git
  4. Adicione o submódulo ao índice do repositório principal:

    git add submodule_path git commit -m "remove submodule"

NOTA: O procedimento descrito acima é destrutivo para o histórico do submódulo, nos casos em que você quer manter um histórico congruente de seus submódulos, você deve trabalhar com um "merge" sofisticado. Para mais informações, eu indico uma referência do Stack Overflow muito completa.

Como ignorar mudanças nos submódulos

Às vezes, os submódulos podem ficar sujos sozinhos. Por exemplo, se você usar submódulos git para rastrear seus plugins vim, eles podem gerar ou modificar arquivos locais como helptags. O git status vai começar a lhe incomodar com essas alterações, mesmo que você não esteja interessado nelas e não tenha intenção de fazer commit delas.

A solução é muito simples. Abra o arquivo .gitmodules na raiz do repositório e para cada submódulo que você quer ignorar, adicione ignore = dirty, como neste exemplo:

[submodule ".vim/bundle/msanders-snipmate"] path = .vim/bundle/msanders-snipmate url = git://github.com/msanders/snipmate.vim.git ignore = dirty

Obrigado a Nils pela ótima explicação.

Zona de perigo! Armadilhas ao interagir com controles remotos

Como o Git Submodule Tutorial no kernel.org nos lembra, há algumas coisas importantes a serem observadas ao interagir com os repositórios remotos.

A primeira é sempre publicar a alteração do submódulo antes de publicar a alteração no superprojeto que faz referência a ele. É uma abordagem fundamental, pois pode impedir que outras pessoas clonem o repositório.

A segunda é sempre lembrar de confirmar todas as alterações antes de executar git submodule update já que, se houver alterações, elas vão ser substituídas!

Conclusão

Armado com essas notas, você deve ser capaz de lidar com muitos fluxos de trabalho recorrentes comuns que surgem ao usar submódulos. Em um texto futuro, vou escrever sobre alternativas ao submódulo git.

Siga as minhas publicações em @durdn e a incrível equipe do @Bitbucket para arrasar no DVCS.

Pronto(a) para aprender Git?

Tente este tutorial interativo.

Comece agora mesmo