Gerenciando seus plugins Rails com GIT + braid
Este cenário surgiu da necessidade de sincronizar o desenvolvimento de mais pessoas num projeto Rails (usando GIT), no que diz respeito a vendor branches externos (plugins). Quando se usa SVN, instalar plugins no Rails com ./script/plugin install -x parece uma maravilha até o momento que você começa a alterar seus plugins.. Quando faz isso, não pode comitá-los, e fica no impasse sobre o que fazer. Nem preciso comentar o quão estranho seria mandar patchs para equipe…
As premissas, antes de tudo, eram:
- Não usar SVN.
- Flexibilidade para SVN e GIT como repositórios remotos.
- Possibilidade de trabalhar em ambiente multiusuário, ou seja, vários desenvolvedores.
Deixe-me explicar a primeira premissa: Usar Subversion implicaria em merges a cada atualização dos plugins. Independente da solução que fosse usada para o merge de um plugin (piston, svnmerge, svn_load_dirs), o Subversion não trabalha bem com arquivos removidos/renomeados/movidos. Seja qual for a estratégia, o fato de fazer merge em repositórios diferentes no Subversion é um “tiro no escuro”: você nunca sabe está realmente idêntico ao repositório que você sincronizou, principalmente quando há mudanças drásticas neles (arquivos removidos/renomeados/movidos), e vai deixando seu rastro de desorganização com o tempo. No site do Piston eles também comentam sobre isso.
Passei horas e horas pesquisando e rascunhando no papel estratégias com repositório central. A solução que mais se aproximou àquela que eu gostaria foi esta aqui, que trabalha com git-submodule.
Fantástica por sinal! Adorei o git-submodule. Como o GIT não permite fazer clones parciais, apenas de repositórios inteiros, achei que fosse a solução. Fiz vários testes, e quando eu havia compreendido muito bem o seu funcionamento, percebi que o git-submodule era muito peculiar para trabalhar com alterações, e certamente causaria confusões na equipe.
Mas essa solução é muito bacana. Se o objetivo for centralizar um repositório de plugins, essa solução pode muito bem ser avaliada.
Mas ela já mata a primeira e a segunda premissa: tem em sua base um servidor Subversion. Ao passo que alguns plugins vêm sendo gerenciados por GIT, já começariamos aqui a ter que colocar repositórios GIT no Subversion! Um retrocesso à nossa meta, na minha opinião
Enfim, o braid!
Até que encontrei o braid (O Fábio Akita já havia comentado sobre ele no Rails Podcast Brasil). O braid é uma ferramenta simples pra gerenciar vendor branches (no nosso caso, plugins do Rails) de repositórios diferentes. Mais ou menos um Piston para GIT.
Resumindo o funcionamento do braid: ele faz uma branch chamada braid/track e nela adiciona clones (git-svn init) para os seus plugins, e ainda faz o merge nesta branch. Quando julgar necessário, você faz merge com sua branch principal.
Experimentando
Para instalar o braid, faça:
1 2 3 4 | $ git clone git://github.com/evilchelu/braid.git $ cd braid $ sudo gem install main open4 $ sudo ruby setup.rb |
Com o braid instalado, inicie um projeto apenas para teste:
1 2 3 4 5 6 7 8 | $ mkdir testing $ cd testing $ git init $ echo "test" > file $ git add file && git commit -m "import inicial" # Jabá brazuca como exemplo: adicionar o plugin feito pelo Carlos Brando $ braid add http://plugins.nomedojogo.com/custom_resource_name --type svn vendor/plugins/custom_resource_name |
Isto cria a seguinte estrutura:
1 2 3 4 | $ git branch -a braid/track * master braid/svn/vendor/plugins/custom-resource-name |
Quando houver modificação no plugin, basta fazer:
1 2 | $ braid update # atualiza o plugin $ git merge braid/track # merge com sua branch principal (master) |
Bacana, mas e a equipe?
Num cenário real (como o que motivou essa estratégia), o repositório está num servidor central que os outros desenvolvedores fazem seus clones. Mas nesse repositório não ficarão os dados da branch recém criada. Então, como os desenvolvedores atualizarão os plugins?
Uma maneira é passar aos demais desenvolvedores os repositórios remotos para que eles adicionem manualmente no .git/config dos seus clones.
1 2 3 4 5 6 7 8 9 10 11 | $ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true # esta parte aqui e mais eventuais outros plugins instalados: [svn-remote "braid/svn/vendor/plugins/custom-resource-name"] url = http://plugins.nomedojogo.com/custom_resource_name fetch = :refs/remotes/braid/svn/vendor/plugins/custom-resource-name |
Sim, isto funciona. Depois basta fazer um braid update.
Mas não é uma forma muito interessante. Ótimo seria explorar o arquivo que o braid cria automaticamente, chamado .braids, que mantém os dados dos vendor branches adicionados:
1 2 3 4 5 6 7 | $ cat .braids --- vendor/plugins/custom_resource_name: local_branch: braid/svn/vendor/plugins/custom-resource-name type: svn branch: master remote: http://plugins.nomedojogo.com/custom_resource_name |
Uma maneira seria modificar o braid e adicionar a funcionalidade de ler este arquivo e adicioná-lo com comandos do GIT. O criador do braid já havia comentado que isso seria feito. Como ainda não foi feito e eu queria testar essa solução, criei um patch e enviei a ele.
Com este patch, um desenvolvedor pode fazer um clone do repositório e, em seguida, executar git rebuild, que reconstruiria a branch e os links remotos a partir do arquivo .braids.
Em breve será feito algo semelhante no braid, seja a partir deste patch ou um novo
É isso!
Vale lembrar que o braid ainda está amadurecendo. O gem, por exemplo, ainda nem foi publicado.
Se você tiver alguma outra idéia ou modelo, fique à vontade em comentar ![]()

Março 12th, 2008 at 09:50
Muito louco esse braid!
Mas, diz ai, o trabalho com Git remoto (no estilo SVN) funciona bem? Os commits não acabam indo p/ máquina local?
Escreve um post sobre isso =) Git c/ Repositório Remoto!
Março 12th, 2008 at 11:27
Bruno,
Funciona bem sim. A diferença é que commits no GIT são realmente locais. Você pode fazer dezenas deles (offline inclusive), e quando estiver certo que quer lançar à sua ORIGEM (note, a origem pode ser a máquina de outra pessoa na rede, nao necessariamente um servidor principal), vc faz:
$ git push
Isto é semelhante ao commit do SVN, ou seja, ele manda para a origem (repositório de onde você fez o clone).
Valeu pela idéia Bruno, vou pensar neste post!
Abraço!
Abril 19th, 2008 at 22:02
Nossa, show de bola o artigo! Tb descobri o braid uns tempos atrás e me quebrou um galhão. Vc sabe se já tem um jeito padrão de dar “freeze” no edge rails, ou por enquanto é na base do braid mesmo? Pelo menos na última gem, rake:freeze:edge ainda tenta acessar o svn (e estranhamente falha na minha máquina, apesar de ainda estarem espelhando os dois repos).
Difícil achar railers brazucas
Keep up the good work 
Abril 20th, 2008 at 13:10
Olá Helder,
Logo logo, na versão 2.1 já estará referenciando o repositório do Github. Eu acho que nesse caso de gerenciar o próprio Rails no braid não é tão útil, considerando que dificilmente você vai alterar o código do próprio Rails. Se vier uma próxima versão do Rails, você remove e dá um freeze novamente
(pelo menos eu faria isso)
Mas se quiser meeesmo, você pode baixar cada componente com o braid (activerecord, actionpack…).
Enfim, eu ficaria na primeira opção
Maio 20th, 2008 at 12:38
[…] Gerenciando seus plugins Rails com GIT + braid […]
Agosto 5th, 2008 at 03:53
brou..da uma olhada no sashimi…
abandonei o braid depois dele e não tive mais dor de cabeça…