O fluxo de trabalho comum para git (git flow) usa ramificações de recursos, onde uma ramificação separada é criada para cada novo recurso. Os desenvolvedores implementam novas funcionalidades nessas ramificações isoladas e, em seguida, mesclam suas alterações de volta na ramificação main
ou master
.
Os benefícios desse fluxo de trabalho são claros: uma ramificação separada pode ser convenientemente implantada e testada no ambiente de controle de qualidade e, se forem detectados erros críticos, ela simplesmente não será mesclada na ramificação main
. Os problemas podem ser corrigidos e o código aprimorado no mesmo ramo.
Enquanto isso, a ramificação principal permanece constantemente implantável e protegida contra esses problemas.
Infelizmente, essa estratégia tem uma desvantagem significativa – mesclar conflitos. Com branches de vida longa, que em algum momento são inevitáveis, esses conflitos podem ser tão difíceis de resolver que fica mais fácil se livrar do branch e começar do zero.
Além disso, quando há muitos conflitos, o resultado da mesclagem pode ser imprevisível.
No entanto, não é a única estratégia possível, e este artigo abordará uma maneira alternativa de gerenciar novos recursos de produtos sem as desvantagens listadas acima.
De acordo com o design do Git, os conflitos de mesclagem acontecem durante a mesclagem quando as ramificações têm conteúdo diferente na mesma linha de arquivo.
Para ilustrar isso, vamos considerar um cenário em que duas equipes estão implementando atualizações no mesmo serviço. A Equipe A está integrando o suporte de cartão de crédito, enquanto a Equipe B está reformulando a página de perfil do usuário. Parece que esses recursos não têm nada a ver um com o outro.
No entanto, verifica-se que o código relacionado ao pagamento estava localizado anteriormente no mesmo local que o código da página de perfil. Assim, ambas as equipes extraíram o código em ramificações separadas e reescreveram a integração.
Agora a questão é: quem será o primeiro a mesclar suas alterações no ramo main
e fingir que o problema não está do seu lado enquanto a outra equipe tenta resolver o conflito resultante?
Ao todo, evitar conflitos de mesclagem é impossível, mas certamente podemos torná-los mais fáceis de resolver usando a seguinte regra bem conhecida:
Se uma ação for difícil e assustadora, faça-a com mais frequência
Em termos do Git, isso significa que precisamos mesclar com a maior frequência possível (idealmente em cada confirmação). E claro, os conflitos vão acontecer com mais frequência nesse caso, mas resolvê-los será muito mais fácil.
É chamado de desenvolvimento baseado em trunk e significa enviar alterações diretamente para o branch main
e evitar o uso de branches quando desnecessário.
No exemplo acima, se ambas as equipes enviassem regularmente suas alterações para o branch main
, perceberiam rapidamente que estavam tentando modificar o mesmo arquivo.
Ainda mais, eles poderiam ter evitado problemas completamente. A segunda equipe teria começado a fazer suas alterações após a primeira equipe já ter modificado o arquivo, considerando essas atualizações.
Um leitor atento pode se perguntar: tudo parece ótimo, mas como fazemos os testes? Ramos por recurso permitem testar toda a nova funcionalidade isoladamente antes do lançamento; se integrarmos mudanças continuamente no ramo main
, não haverá chance para isso.
Um sinalizador de recurso, ou um recurso de alternância, é um sinalizador dinâmico simples que permite alternar o recurso específico em tempo de execução. Comumente, sinalizadores de recursos também permitem habilitar ou desabilitar recursos para grupos específicos de usuários, como engenheiros de controle de qualidade, funcionários, clientes específicos, etc.
Os sinalizadores de recurso têm várias vantagens extras:
O uso de sinalizadores de recursos torna mais seguras as alterações por push no branch main
. Enquanto o sinalizador de recurso estiver desativado, as alterações não afetarão ninguém.
Essa técnica permite trabalhar diretamente com o branch main
ou criar branches de vida curta. Portanto, os conflitos de mesclagem tornam-se bastante raros e são resolvidos rapidamente.
Em resumo, o desenvolvimento baseado em trunk combinado com sinalizadores de recursos é uma técnica excelente que ajuda a evitar muitos problemas gerados por alterações conflitantes em ramificações de recursos.
No entanto, como sempre, não existe um tamanho único. Funciona para um pequeno número de equipes que estão trabalhando no mesmo repositório – aumentar esse número geralmente requer alguns ajustes.
Além disso, é sempre possível usar os dois métodos: usar ramificações de recursos ou sinalizadores de recursos, dependendo da situação e da tarefa específica.