Hoje vou falar sobre algo bem interessante, que deixa o versionamento do nosso código bem organizado. Estão em dia com os assuntos Semantic Version
e Git flow
?
Aposto que já utilizou essas regras, mas não tinha um conhecimento mais profundo sobre o assunto, ou já sempre utilizou seguindo à risca.
Já conheço e sigo o Git flow
, a um bom tempo. Inclusive um dos meus projetos no github é sobre a documentação do mesmo. Não reinventei a roda, é mais para ter um registro de fácil acesso, para futuras explicações ou consultas.
Sobre Semantic Version
, o site oficial que está na versão 2.0.0
, explica com detalhes as regras.
Estudando os conteúdos acima, basta ter uma disciplina inicial para os processos e regras.
Tomada de decisões
Muitas perguntas podem surgir na cabeça com algumas situações. Vou ilustrar algumas.
-
Digamos que estamos na versão 2.2.0 na branch
master
. Estamos planejando um novo recurso (feature), então a próxima versão deve se tornar 2.3.0. Em seguida, o cliente relata um bug crítico, forçando-nos a preparar umhotfix
. Nós corrigimos o bug e colidimos a versão para 2.2.1. Mas, dados os 'insights' obtidos com a correção do bug, agora percebemos que talvez precisamos quebrar a API pública para que a feature funcione da maneira que queremos. E se fizermos isso, não devemos mais colidir com a versão 2.3.0. Em vez disso, devemos mover para a versão 3.0.0.
Regra: A alteração de versão ocorre quando nós nos ramificamos do desenvolvimento para o release, ou quando nos ramificamos do master para a branch de hotfix.
- Convenção de nomenclatura na branch de
dev
. Uma vez que todas as mudanças nas outras branchs devem ser mescladas de volta paradev
, acho que a nomeação deve refletir quedev
é praticamente sempre a versão mais recente do produto. Por isso, é interessante usar a convençãoa.b.c-wip.d
, ondewip
(work-in-progress) significa trabalho em andamento ed
é o número da compilação (build).
Regra: Sempre certifique-se de que o número de versão na branch de dev está em sincronia com o número mais recente em qualquer branch de hotfix ou release.
Exemplo:
A branch de dev
estava em 1.2.0-wip.123 quando criamos a branch hotfix
(hotfix/1.2.1). Seguindo a última regra, quando nós juntamos de volta a branch de dev
, ele é será 1.2.1-wip.x.
Esta regra pode ficar complicada quando estamos trabalhando em um hotfix
e uma branch de release
simultaneamente. Na maioria dos casos, o número de versão da branch de release
deve superar a de hotfix
. Especialmente porque provavelmente queremos mesclar alterações da hotfix
de volta para a branch de release
antes de envolvê-lo.
- Convenções de nomenclatura nas branches de
release
. Eu não espero que osreleases
permaneçam nesta branch por muito tempo, então o ciclo de vida completo de alpha/beta/rc1/rc2 parece um exagero. No final, podemos usar o rc-prefixo, o que leva à seguinte notação:a.b.c-rc.d
. Novamente,d
é o número de compilação (build).
Vamos continuar com o exemplo. Nós decidimos quebrar a API, então criamos uma nova branch de release
(release/2.0.0). A primeira marca nesta branch deve então ser 2.0.0-rc.x
, onde x
é o número de compilação. Mas o que deveria ser x
neste caso? Isso traz a questão sobre quando o contador deve ser redefinido, se alguma vez.
Vamos examinar uma alternativa:
Alternativa: Redefinir o contador de compilação sempre que o número de versão for colidido
Juntamente com o número de versão, isso garante exclusividade. Também parece muito mais agradável, já que o número de compilação raramente atingirá além de três dígitos.
No entanto, ele introduz um outro problema: lembrar de redefinir o contador sempre que você alterar o número da versão. Ou, se vamos para a automação completa, como detectar quando o número da versão mudou.
Regra: Assegure-se de que cada tag de controle de versão seja exclusivo no repositório.
Exemplo passo a passo
Atividade do projeto | Tag |
---|---|
O projeto começa, o master está vazio e estamos fazendo o commit do nosso primeiro recurso no desenvolvimento | 0.0.0-wip.1 |
É feito o commit da tarefa A na branch develop de uma branch feature |
0.0.0-wip.2 |
Correção rápida de erros diretamente no desenvolvimento | 0.0.0-wip.3 |
É feito o merge da tarefa B em develop de uma branch feature |
0.0.0-wip.4 |
Primeiro 'minor release'! Uma Branch é criada a partir de develop (release/0.1.0) e reseta o contador da compilação |
0.1.0-rc.1 |
Mais um commit foi necessário | 0.1.0-rc.2 |
Para manter o desenvolvimento sincronizado, fizemos o merge da branch 'release' de volta, criando um commit de mesclagem | 0.1.0-wip.3 |
Um membro da equipe faz um commit de um recurso C em develop |
0.1.0-wip.4 |
Release em produção: fizemos o merge de release/0.1.0 em master e develop |
0.1.0-release.5 0.1.0-wip.6 |
É feito um commit de uma pequena refatoração em develop |
0.1.0-wip.7 |
Um bug crítico é relatado na produção; Criar uma branch hotfix |
hotfix/0.1.1 0.1.1-hotfix.1 |
É feito o merge da versão atualizada de volta para develop e assim evitar duplicação de tags (uma vez que o contador tem que ser redefinido) |
0.1.1-wip.2 |
Enquanto isso, outro commit de refatoração em develop |
0.1.1-wip.3 |
O hotfix é finalizado |
0.1.1-hotfix.4 |
A ser feito o merge para master e develop |
0.1.1-release.5 0.1.1-wip.6 |
É feito o merge de outra branch de feature em develop |
0.1.1-wip.7 |
Outra minor release . Criaremos a branch release/0.2.0 de develop e resetamos o contador da compilação (build) |
0.2.0-rc.1 |
Conclusão
Pode ficar confuso de início, se não estiver familiarizado com o processo. Mas nada melhor que a prática. Então, crie o seu repositório de testes e comece a praticar. Tendo mais exemplos para ilustrar, estarei atualizando esse artigo ou criando um novo sobre o assunto. Feedbacks e novos cenários, são bem-vindos.