Fazendo um Merge sem fazer besteira


Existem alguns sistemas de controle de versão bastante conhecidos, dentre os quais ressaltamos o CVS (o mais antigo e tradicional) e o Subversion (para mim, e outros mais, o melhor e mais avançado). Na Riopro utilizamos o Subversion para manter a rastreabilidade das classes e documentações utilizadas em nossas aplicações.

Um sistemas de controle de versão permite que além da versão estável e principal (por padrão o diretório trunk) a criação de diversos ramos, os chamados Branches. Com isso temos a liberdade de criar modificações mais drásticas (como passar da versão 1 para a versão 2 de uma aplicação) sem afetar os usuários/clientes que utilizam a versão estável, e ao mesmo tempo mantendo o versionamento para esse ramo. Um dos momentos mais complicados ao usar um sistemas de controle de versão de arquivos é o momento de realizar o Merge entre diferentes ramos ou de um ramo com o diretório principal. É disso que trataremos nesse artigo.

Usaremos para o nosso artigo o Team com o Subclipse, que são plugins do Eclipse e fornecem interface integrada tanto para o Subversion. Existem outros clientes para o Subversion, como o excelente TortoiseSVN (que para mim é o melhor existente para o Windows) também da Tigris, como o Subclipse. Outro ótimo cliente é o SmartSVN, que tem como principal virtude ser feito em Java, e portanto ser portável, além de leve.

O Merge é usado principalmente para 2 coisas: atualizar um ramo com alterações feitas no diretório principal ou em outro ramo, ou para fazer a atualização mais profunda da aplicação (passar um ramos para o diretório principal).

TENHA SEMPRE MUITO CUIDADO AO FAZER UM MERGE, E DE PREFERÊNCIA, FAÇA UM BACKUP DO REPOSITÓRIO ANTES. ESSE ARTIGO NÃO GARANTE EM NENHUMA HIPÓTESE QUE SEU MERGE TERÁ SUCESSO. UTILIZE AS INFORMAÇÕES AQUI DISPONIBILIZADAS POR SUA CONTA E RISCO.

Mãos na massa. Na hora de fazer o Merge, sempre fico em dúvida sobre qual a maneira mais garantida de proceder. Por isso, vamos a um exemplo prático da migração de um ramo para o diretório principal, que para mim é sempre o momento mais crítico.

Digamos que tenhamos aberto um branch que chamaremos de NOME_DO_BRANCH. Após realizarmos todas as modificações e aprovarmos, vemos que é hora de passa-lo para o trunk.

a tela de merge no Eclipse

Todas as últimas modificações do NOME_DO_BRANCH já foram realizadas e comitadas. A primeira coisa que fazemos, então, é voltar o nosso repositório para usar o trunk. Fazemos isso utilizando o Switch to Another Branch/Tag. Estando com a nossa versão atual no HEAD do trunk, o que queremos agora é trazer todas as atualizações feitas no NOME_DO_BRANCH para o trunk.

Escolhemos então MERGE para juntar os dados. Na URL do From, devemos colocar a URL do trunk e marcar a HEAD (para dizer que estamos juntando à última cópia). Para a URL To devemos colocar o endereço para o branch e marcar HEAD também, para que realizemos a junção com a última versão do branch.

Antes de prosseguir, fazemos primeiro fazemos um Dry Run para verificar se existe algum conflito. Em não havendo, podemos clicar no Merge (se houver conflito, a verificação dos arquivos é manual e o mesmo vai apontar os conflitos).

Após realizarmos o Merge, o Subversion terá alterado apenas a nossa cópia. Podemos então compilar tudo, realizar os testes necessários para validar a versão “conjunta”. Em estando válida, simplesmente fazemos um COMMIT e a versão do trunk será atualizada para ser compatível com a versão do NOME_DO_BRANCH.

Informações e Links

Junte-se comentando, lendo o que os outros dizem ou colocando um link a partir do seu blog.


Outros Artigos
Descobrindo os IP’s e Mac Addresses da sua rede
Conectando a instâncias do MSSqlServer por JDBC

Comente

Tire um tempo para comentar e nos dizer o que você acha. Alguns códigos HTML são permitidos para formatação.

Comentários dos Leitores

Não entendi nada.
Uns exemplos ajudariam.

Edson, esse não é um artigo introdutório sobre o Subversion, mas sim, cobrindo apenas um item específico, o Merge.

O exemplo foi dado e a imagem mostra claramente como fazer. O seu problema pode ser de compreensão de como funciona o Subversion em si. Para isso sugiro começar pelo Wiki, que descreve o que faz a ferramenta.

De qualquer forma acho que depois vou ampliar o escopo do artigo para mostrar como se cria um branch.

Sabe porque fazer merge no subversion é “tenso”? Porque subversion é uma b(…). (editado pois opinião é livre no site, mas palavrão não)

discordo totalmente da opinião acima…

Muito legal o passo a passo, vou ter que fazer isso daqui uns dias e já tava com um certo medo (já tive uns probleminhas com o Subversion).

Só uma crítica: as fotos estão MUITO pequenas (do tamanho de thumbnails) e não são clicáveis (pelo menos no meu navegador - Firefox).

Ah, e valeu a dica do SmartSVN também ! Vou testar…

crítica pertinente. Não vi que tinha ficado sem o link da imagem….

Valeu Otávio! Explicação simples (sem muita firula) mas bem detalhada. Parabéns!

Boa explicação, bem sucinta, estava precisando de algo assim para clarear minhas idéias para o curso que estou preparando.

Abraço!

Rafael, que bom. O seu curso é sobre o quê?

Q? entendi nada ??

Um link explicando o que é Subversion talvez te ajude:

Introdução:
http://en.wikipedia.org/wiki/Subversion_%28software%29

FAQ Oficial:
http://subversion.tigris.org/faq

Eu imaginei que o Merge seria para mesclar as modificações realizadas em um Branch com outro Branch (ou com o Trunk).
Tentei fazer um Merge de um Branch com o Trunk. Esse Merge apenas trouxe as modificações que ocorreram no Branch para o Trunk, e as alterações que eu havia feito no Trunk foram perdidas.
É esse mesmo o objetivo do Merge ou eu estou fazendo algo errado???

Gustavo,

Esse é realmente o objetivo do merge. Ele modifica a versão commitada no trunk. Mas ele deve ter te perguntado algo sobre isso antes de fazer o merge. De qualquer forma, se você está “trabalhando” no trunk e alguém fez um merge nele, no update ele vai tentar fazer um merge com sua versão local.

Talvez seu problema fosse resolvido mais facilmente usando patches ao invés de merge. Para fazer um patch entre o seu branch e o trunk, você pode fazer um checkout novo do trunk, copiar os arquivos do branch por cima do trunk e aí gerar um diff do que foi modificado. Esse diff é um patch que você poderia aplicar a sua versão local ainda não commitada.

Não sei se você errou. Na verdade, acho que o único erro que você parece ter cometido é ter perdido as suas modificações do trunk não versionadas :). Se é que aconteceu isso.

Dá uma olhada sobre patches aqui:
patch

Otávio, obrigado pelo auxílio.
Eu havia entendido errado o objetivo do Merge. No meu caso, o patch é mais indicado, exatamente como você disse.
Era exatamente isso que eu estava precisando, eu já fiz alguns testes aqui e consegui o resultado que desejava. Ao aplicar o patch eu preciso fazer a “mescla” manualmente, no entanto, as ferramentas de Merge auxiliam bastante.
Obrigado.

Então, eu já tive alguns problemas com Merge no sentido dele “querer” voltar arquivos do Trunk para versões mais antigas (pois como o pessoal continua trabalhando no Trunk ocorrem essses conflitos).

Tem alguma sugestão para minimizar este risco?

Reinaldo, não tenho certeza se entendi o que você disse. Realmente, conflitos são coisas comuns em merges e sempre serão (afinal, a resolução do problema de 2 pessoas mudarem a mesma linha de um arquivo realmente é complicado ficar a cargo do computador). Só que existem ferramentas que lidam pior ou melhor com isso.

Atualmente estou bastante impressionado com o git. Branches e merges ficam mais simples com o git. Vale à pena dar uma olhada.

tenho ainda que aprender a fazer um branch no eclipse, como faço e como utilizo esse branch

Fazer um branch é fácil. Difícil é voltar ele pro trunk depois :).

Sem brincadeira, se for só para fazer um teste em algo nada crítico, clica com o botão direito em cima do projeto e vai em Team | Branch/Tag. Vai abrir uma tela sugerindo “From” o seu trunk (o que é normal, pois, normalmente, estamos criando um ramo a partir da estrutura principal). No “to url” ele sugere o trunk também (o que é impossível). Troque /trunk por /branches/NOME_PARA_SEU_BRANCH. Digite um texto para commit e pronto. Branch criado. Um branch é uma cópia de uma determinada revisão (normalmente HEAD, ou a última) que terá “vida independente”.

Leia sobre branches antes de começar, ok? Vai evitar grandes besteiras

Então, descobri meu problema com o Merge!!

Meu problema era a compreensão de como o merge funciona.

Agora entendi que o merge pega os arquivos alterados ENTRE as duas URLs informadas e mescla com a cópia de trabalho. Sendo assim, no meu caso que eu estou trabalhando com uma versão anterior e corrigindo Bugs nela eu precisava colocar a ultima URL válida, até a URL do meu Branch e os arquivos são mesclados com o Trunk (que é minha cópia de trabalho).

Antes eu fazia o merge do meu trunk com meu Branch, entretanto meu Branch é de uma versão anterior a que eu estou trabalhando, por isso o SVN tentava voltar alterações que eu havia feito.

Espero ter ajudado em algo com essa zona de palavras.
Abraço.

Reinaldo. É isso. Ou quase isso. Você pode querer atualizar seu Branch com coisas que foram feitas no trunk. Por exemplo, aqui na Riopro, quando usávamos o SVN, optamos (depois de um tempo) por manter sempre a versão de desenvolvimento no Trunk. E criávamos um branch com a versão antiga porque essa sofre menos manutenção. Assim mergeamos apenas uns poucos arquivos.