13 de novembro de 2014

Fluxo de trabalho com git

Introdução

Trabalhar com git, de modo geral, é simples. Alguns comandos são mais complicadinhos, mas o básico a gente aprende muito rápido. Tutorial sobre git é o que não falta.

No entanto, pouca gente fala sobre fluxo de trabalho. Os problemas começam a aparecer quando você trabalha com mais uma pessoa. Se entrar mais gente para a equipe, as coisas podem ficar confusas bem rápido.

Para abordar o assunto de forma resumida, preparei uns slides que chamei de Gitlab flow Solo, que baseia-se no Gitlab flow.

Ainda assim, algumas perguntas ficam com resposta vaga ou apenas subentendida. Existem boas fontes sobre esse assunto, mas os processos vão melhorando e precisamos avaliar o que nos serve ou não. Então resolvi escrever um pouco sobre isso, detalhando a apresentação.


A importância de ter nomenclaturas

Boa comunicação é fundamental e nomenclaturas simples ajudam muito.

Exemplos de nomenclaturas para nomes de branches:

Feature branches

Nomeie seus feature branches com base no seu sistema de tickets (ou issues, ou demandas, ou atividades, seja lá como for o nome que você use) para facilitar a identificação das atividades.

Não importa qual sistema você está usando para controlar as atividades. Use o número da atividade no nome do branch.

Exemplo: o ticket 284 é "enviar email quando orçamento for aprovado". Seu feature branch será chamado "ticket284-enviar-email-qdo-aprovar-orcamento".

Assim fica muito fácil identificar pelo nome do branch a qual atividade ele se refere. Como também fica fácil identificar qual branch atende a determinada atividade.

Branches para correção de bugs

Use o mesmo princípio para nomear os feature branches, mas inicie seu nome com "bug".

Exemplo: o ticket 73 é "está mostrando salário para todo mundo". Seu branch será chamado "bug73-mostra-salario-pra-todo-mundo".

Branches de release

Se você vai lançar a release 2.1, chame seu branch de "RELEASE-2.1". Simples assim.

Branches estáveis de produção

Seguindo o mesmo princípio dos branches de release, se a versão que você está implantando é a 2.6, chame seu branch de "PRODUCAO-2.6" ou "2.6-PRODUCAO".

Aqui, vale uma observação. Ao contrário dos branches de feature ou de correção, os branches de release e de produção não devem receber manutenção direta. Em outras palavras, você não vai dar commit neles. Por isso eles têm um nome diferenciado, com letras maiúsculas ou a versão no início do nome do branch. Seguindo um procedimento assim, fica mais difícil o checkout indevido nesses branches.

Essas são apenas sugestões. O importante é que a nomenclatura seja simples de usar e de entender. Afinal, boa nomenclatura viabiliza boa comunicação.

Perguntas Frequentes

Como mantenho um histórico das versões de produção?

Simples:
  1. Crie um novo branch para cada versão estável implantada em produção.
  2. Use versionamento semântico.

Exemplo: a primeira versão é a 0.1.0. Portanto, você vai ter um branch PRODUCAO-0.1. Quando a próxima versão for lançada, teremos o branch PRODUCAO-0.2. Com o passar do tempo, teremos o branch PRODUCAO-1.0, e assim por diante.

Esses branches permanecem no projeto por muito tempo, pois permitem voltar uma versão de meses ou anos atrás. Isso é bastante útil quando você tem usuários usando versões diferentes do seu produto.

Dica: não crie branches para patches (a última parte da versão semântica). Integre os patches no branch estável que ele corrige e use tags para identificar os patches.

Por que não devo criar branch para um patch?

Porque os branches de produção são usados para manter um histórico útil de versões estáveis. Patches nada mais são do que uma das formas para se chegar a uma versão estável.

Os patches corrigem o que escapou dos testes. Eles não são versões. São correções de versões. Portanto, podem ser considerados como parte da etapa de desenvolvimento, em busca de uma versão estável e correta.

Pensando em versões estáveis ao longo do tempo, o que interessa para um usuário é ver uma lista de branches assim:
  • PRODUCAO-1.0
  • PRODUCAO-1.1
  • PRODUCAO-1.2, ...
Não é importante saber que a versão 1.0 teve, por exemplo, 5 patches. Nem que a 1.1 teve 2 patches. O importante é ter a versão estável 1.0 ou 1.1.

Esse é o raciocínio por trás do histórico útil de versões estáveis.

Quando uso tags e quando uso branches?

Resposta resumida:
  1. Sempre que você for desenvolver, corrigir ou fazer um experimento, crie um branch.
  2. Toda vez que você fizer deploy de uma versão estável (implantar em produção), crie um branch e uma tag apontando para esse branch.
  3. Toda vez que você integrar um patch em produção (vindo de um branch de correção), crie uma tag para esse patch.

Exemplos:
  • Para o branch PRODUCAO-0.1, crie a tag v0.1.
  • Quando integrar o patch 0.1.1 no branch PRODUCAO-0.1, crie a tag v0.1.1.

Para as versões de patch (0.1.1, 0.1.2) crie tags (v0.1.1, v0.1.2). Por que isso? Porque as tags vão permitir voltar para qualquer versão sem poluir o repositório. As tags dos patches são úteis para os desenvolvedores.

A regra básica é: se você quer ver uma versão estável, faça checkout no branch desejado, que tem a versão estável. Mas se você quer uma versão que não é estável, faça checkout para a tag equivalente.

Quando devo apagar um branch?

Não existe uma regra para isso, mas eu apago meus feature branches ou meus branches de correção (patches) quando percebo que o código implantado está funcionando há pelo menos uma semana.

Os branches de produção ficam por muito tempo (anos) no projeto.

Já os branches de release eu apago assim que a release é implantada.

Tenho muitos conflitos de merge. Como evitá-los?

Dicas:
  1. Faça integração (merge) com mais frequência.
  2. Não fique sem integrar o master com seu branch por muito tempo (1 dia).
  3. Antes de integrar com o master, faça num branch de teste:
    • Crie um branch de teste a partir do master.
    • Faça merge do seu feature branch para esse branch de teste.
    • Se não houver conflitos, não haverá quando você integrar com master.
    • Se houver, você pode se antecipar ao problema.
  4. Atualize seu master (pull) com frequência.
  5. Se você estiver trabalhando em um branch compartilhado, pare com isso imediatamente!

Minhas mensagens de commit não esclarecem muita coisa. O que faço?

Veja a apresentação: Git commits - como, quando e por quê?

11 de fevereiro de 2014

How to install MySQL 5.6 in Ubuntu 12.04 Precise

So, you are using Ubuntu 12.04 Precise Pangolin with MySQL 5.5 installed and you want to upgrade to MySQL version 5.6.

But, before upgrading, you should make a backup of your data:
$ sudo mysqldump -A --events --user=root --password=root > ~/backup_of_mysql_v5.5.sql

Now, let's go on. Since there's no official MySQL 5.6 available through Ubuntu repositories, you can add the unofficial MySQL 5.6 repository and install it with:
$ sudo add-apt-repository ppa:ondrej/mysql-5.6
$ sudo apt-get update
$ sudo apt-get install mysql-server

If you get an error telling you add-apt-repository command was not found, install it with:
$ sudo apt-get install python-software-properties

After installing the new version, you should use mysql_upgrade to convert your tables to newer format:
$ sudo mysql_upgrade --verbose --force --user=root --password=root

Notes:
  1. I assume "root" as your user and password. Change it match your installation.
  2. mysql_upgrade output can be long. So, redirect it to some logfile.
  3. Don't upgrade without a backup. Never!

22 de janeiro de 2014

Outra versão do mesmo programa

Eu sempre digo que o git é como o vim. Sempre você descobre um comando novo ou um recurso legal em comandos que você já usava.

Esses dias eu precisei de um programa na versão que eu estava mexendo em outro branch. Como fazer? A primeira opção que me veio à mente foi:
  1. clonar o repositório;
  2. dar checkout no branch (feature-x) que tinha o arquivo (nova-regra.py) na versão que eu precisava;
  3. copiar o programa para meu diretório de trabalho atual;
  4. apagar o clone temporário do repositório.
Isso faria sentido se eu não estivesse usando o git. Porque o comando git show aceita receber a revisão onde está o arquivo que eu quero listar. Era isso que eu precisava! Com isso, consegui pegar o arquivo rapidinho com o seguinte comando:
$ git show feature-x:./src/clientes/nova-regra.py > minha_nova_regra.py


O legal é que além de um branch, você pode informar uma tag ou o hash de um commit. Ou seja, qualquer "treeish". No exemplo acima, ele pegou o HEAD (commit mais recente) do branch feature-x. Mas por que o redirecionamento do output para um arquivo? Porque o git show sempre mostra na saída padrão.

Caso você não saiba exatamente qual o nome do arquivo desejado e precise listar o conteúdo do diretório antes, existe um comando para isso:

$ git ls-files --with-tree=feature-x -- src/clientes


O git ls-files também me permite informar um "treeish" no argumento --with-tree.