Subárvore Git: a alternativa ao submódulo Git
Nicola Paolucci
Representante do desenvolvedor
A Internet está repleta de artigos sobre por que você não deve usar os submódulos do Git. Embora os submódulos sejam úteis para alguns casos de uso, eles têm várias desvantagens.
Existem alternativas? A resposta é: sim! Existem (pelo menos) duas ferramentas que podem ajudar a rastrear o histórico de dependências de software em seu projeto, permitindo que você continue usando o Git:
Subárvore do Git
- Repositório do Google
Neste post, vou analisar o git subtree
e mostrar por que é uma melhoria – embora não perfeita – em relação ao git submodule.
O que é git subtree e por que devo usar?
O git subtree
permite aninhar o repositório dentro de outro como um subdiretório. É uma das várias maneiras pelas quais os projetos Git podem gerenciar as dependências do projeto.
Por que você pode querer considerar o git subtree
- O gerenciamento de um fluxo de trabalho simples é fácil.
- As versões mais antigas do Git são suportadas (ainda mais antigas que a v1.5.2).
- O código do subprojeto está disponível logo após a conclusão do clone do superprojeto.
- O
git subtree
não exige que os usuários do repositório aprendam nada de novo. Eles podem ignorar o fato de que você está usando umgit subtree
para gerenciar dependências. - A
subárvore do git
não adiciona novos arquivos de metadados como o submódulo do git faz (ou seja, .gitmodule). - O conteúdo do módulo pode ser modificado sem ter uma cópia separada do repositório da dependência em outro lugar.
Desvantagens (mas, em nossa opinião, são aceitáveis):
- Você deve aprender uma nova estratégia de merge (
git subtree
). - Contribuir com o código de volta para os subprojetos é um pouco mais complicado.
- A responsabilidade de não misturar o código do superprojeto e do subprojeto nos commits é sua.
Material relacionado
Como mover um Repositório do Git completo
VER SOLUÇÃO
Aprenda a usar o Git com o Bitbucket Cloud
Como usar o git subtree
O git subtree
está disponível na versão stock do Git desde maio de 2012 — v1.7.11 e superior. A versão instalada pelo Homebrew no OSX já tem uma subárvore conectada, mas, em algumas plataformas, você pode precisar seguir as instruções de instalação.
Deixe-me mostrar o exemplo canônico de rastreamento de um plugin do Vim usando o git subtree.
O caminho rápido e sujo sem rastreamento remoto
Se você quiser apenas alguns forros para cortar e colar, basta ler este parágrafo. Primeiro, adicione git subtree
em uma pasta de prefixo especificada:
git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
(A prática comum é não armazenar todo o histórico do subprojeto no repositório principal, mas se você quiser que ele seja preservado, basta omitir a marcação –squash.)
O comando acima produz esta saída:
git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'
Como você pode ver, essa ação registra um merge commit ao condensar todo o histórico do repositório vim-surround em um:
1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]
Se depois de um tempo você quiser atualizar o código do plugin do repositório upstream, você pode fazer um git subtree
pull:
git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
É muito rápido e tranquilo, mas os comandos são um pouco longos e difíceis de lembrar. Podemos tornar os comandos mais curtos adicionando o subprojeto como um controle remoto.
Adicionando o subprojeto como um controle remoto
Adicionar a subárvore como um controle remoto nos permite consultá-la de forma mais curta:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Agora podemos adicionar a subárvore (como antes), mas agora podemos nos referir ao controle remoto de forma resumida:
git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
O comando para atualizar o subprojeto posteriormente se torna:
git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Contribuindo de volta ao upstream
Agora a gente tem liberdade para fazer o commit das correções para o subprojeto no diretório de trabalho local. Quando é hora de contribuir de volta para o projeto upstream, precisamos bifurcar o projeto e adicioná-lo como outro controle remoto:
git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git
Agora podemos usar o comando subtree push como o seguinte:
git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main
Depois disso, estamos prontos e podemos abrir um pull request para o mantenedor do pacote.
Posso fazer a mesma coisa sem usar o comando git subtree?
Sim! Sim, você pode. O git subtree
é diferente da estratégia de merge de subárvore. Você ainda pode usar a estratégia de merge, mesmo que por algum motivo o git subtree
não esteja disponível. Veja como:
Adicione a dependência como um simples git remote
:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Antes de ler o conteúdo da dependência no repositório, é importante gravar um merge para que possamos rastrear todo o histórico da árvore do plug-in até este ponto:
git merge -s ours --no-commit tpope-vim-surround/main
Quais saídas:
Automatic merge went well; stopped before committing as requested
Em seguida, lemos o conteúdo do objeto de árvore mais recente no repositório de plugins no diretório de trabalho pronto para o commit:
git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main
Agora podemos fazer o commit (e vai ser um commit de merge que vai preservar o histórico da árvore que lemos):
git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround
Quando for atualizar o projeto, agora é possível extrair usando a estratégia de merge de git subtree
:
git pull -s subtree tpope-vim-surround main
O git subtree é uma excelente alternativa
Depois de ter usado os submódulos git por um tempo, você vai ver que o git subtree
resolve muitos dos problemas com o submódulo do git. Como de costume, com todas as coisas do Git, há uma curva de aprendizado para aproveitar ao máximo a função.
Me siga no Twitter @durdn para saber mais sobre o Git. E confira o Atlassian Bitbucket se você estiver procurando uma boa ferramenta para gerenciar os repositórios do Git.
Atualização: depois de publicar este artigo, também escrevi um artigo sobre o poder da subárvore do Git.
Compartilhar este artigo
Próximo tópico
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.