Submodules & GIT - usando bibliotecas externas.
Quem está acostumado em gerenciar suas bibliotecas em svn usando o recurso
externals, quando considera usar o GIT, geralmente tem dúvida a respeito de como trabalhar. Já escrevi aqui um artivo a respeito de
svn externals e agora que estou migrando pro git então escrevo este aqui também para quem quiser me acompanhar.
Dois recursos normalmente surgem quando pesquisamos a respeito do assunto:
- submodules
- subtree merge strategy
Vamos tratar aqui do primeiro, porém quem quiser pesquisar o segundo, veja a comparação entre
submodules e subtree merge strategy na documentação.
O que são submodules?Na documentação diz que submodules ou submódulos permitem repositórios externos serem adicionados dentro de um subdiretório dedicado da arvore do nosso projeto, sempre apontando para um commit específico.
Bom... uma parte de cada vez:
repositórios externossão outros repositórios em git.
diretórios dedicadoo diretório onde o submódulo fica tem sua arvore específica, inclusive a pasta .git com suas próprias configurações. Não pode ser feito merge com a arvore do repositório pai.
commit específicoquando adicionamos um submódulo a uma arvore, estamos adicionando um commit específico. Isso quer dizer que atrelamos ele a uma versão (um SHA). Toda vez que alguém baixar este projeto e pedir o submódulo ele vai receber esta versão mesmo que o repositório original esteja bem mais adiantado.
Isso é legal. Quero um pra mim. Como eu faço para criar um submódulo?você deve usar um comando semelhante à este aqui (nessa hora o melhor mesmo é consultar o
manual do git):
git submodule add [URL do repositório] [pasta de destino]
git submodule add http://github.com/brunoreis/pspec.git extlibs/pspec
com isso ele vai criar um repositório para o pspec na pasta
extlibs/pspec. Vale a pena dar uma olhada nesta pasta, dentro do diretório .git, e ver o que tem nos arquivos texto de configuração. Com certeza vai auxiliar a encaixar as peças do quebra-cabeças. Ah, e também olhe o .git da raiz do seu projeto.
Bom, então é só isso? Meu submódulo está criado, posso mandar meu projeto para o github e ficar famoso porque uso submódulos e o
pspec para especificar e testar meu software?
Muita hora nessa calma! Ainda temos algumas coisas a fazer antes. Ao criar o submodule, como já dissemos antes, atrelamos ele a um SHA específico. Os arquivos do repositório, a princípio, não ficam dentro do nosso repositório, mas o SHA sim. Temos então que adicionar o subdiretório criado à arvore original para que ele possa ser integrado ao nosso repositório.
Fazemos assim:
git add extlibs/pspec
git commig -m "agora sim com pspec"
Agora está lá... e se quiser subir para o repo de origem, não esqueça de fazer um push.
Isso quer dizer que quem fizer checkout no meu projeto já vai baixar o submódulo?Não. Como já falei antes, você mandou apenas o SHA. Assim quando você fizer checkout vai trazer apenas uma referência à aquele submodulo, sem baixar o conteúdo do mesmo. Então após fazer checkout do seu repo, você ainda vai ter que fazer o seguinte:
git submodules init
git submodules update
Com isso ele vai trazer o conteúdo do(s) submódulos de acordo com o SHA de cada um.
E como eu faço pra saber se um projeto que baixei tem submódulos?essa é fácil, é só rodar
git submodules
ele mostra os submódulos e também o SHA de cada um.
Beleza, mas agora eu sei que tem algo novo que eu preciso em um submódulo, como eu atualizo ele?Simples, como o submódulo tem lá sua arvore e seu .git, etc.. porém este repositório está atrelado a um commit (sha) específico. Então precisamos fazer um checkout do branch que você quer, ex:
git checkout master
depois disso você pode usar
git pull
para atualizar.
Ah, e lembre-se de que depois que você fez isso, você tem que adicionar novamente o submodule ao repositório e fazer um commit (da atualização do SHA) para que os outros possam ter essa atualização.
Ao fazer essa atualização não coloque uma barra depois do nome do submodule. Se você fizer isso vai bagunçar tudo. Ou seja, use:
submodule add extlibs/pspec
mas NÃO USE
submodule add extlibs/pspec/ <--------------- Essa barra faz @#$@%@!!
Ta bom, ta bom....Hum.... e....
Se eu quiser atualizar todos de uma vez?É só fazer assim:
git submodule foreach "git pull"
Esse comando eu achei muito interessante. Ele roda por todos os submódulos e executa o comando que for passado para ele, no noso caso o pull. Não esqueça de mandar esta alteração adicionando os submodules novamente à arvore principal.
Beleza, mas agora que estou no meu projeto, vi que tem um bug no repositório do submódulo. Tem como eu arrumar isso sem fazer checkout do sub em outro diretório?Sim. Você pode entrar no dir do submódulo, fazer um checkout, alterar, fazer um commit e mandar novamente para o repo original.
Se você fizer isso e encontrar um erro dizendo que o original não aceita commits deste, leia este post a respeito do uso de
"bare repositories".
Ta Bom.
Espero que você tenha sucesso usando os submódulos. Eles me parecem bem mais simples e dinâmicos que os externals do svn. Ainda estou aprendendo o git, então deve ter algo aqui que pode ser feito de uma maneira melhor ou então algo que você não entendeu. Peço que você acrescente seu comentário que se eu puder, respondo. Assim agregamos mais informações para os próximos não terem que ficar pesquisando as mesmas coisas que nós.
Sucesso!
--------------
Ah...
Algumas referências citadas e usadas aqui:
http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html
http://book.git-scm.com/5_submodules.html
https://git.wiki.kernel.org/index.php/GitSubmoduleTutorial
http://stackoverflow.com/questions/804545/what-is-this-git-warning-message-when-pushing-changes-to-a-remote-repository