Anatomia de um bom commit

Commits, check-ins, patches. Não importa o nome que você (ou seu sistema de controle de versão) usa, eles são parte essencial da sua imagem como dev. Commits desleixados queimam seu filme e commits bem organizados mostram que você se importa com sua profissão. Mas isso não os impede de serem muitas vezes renegados. Depois de algum tempo desenvolvendo, você cria um certo instinto para o que faz um bom commit. Aqui está minha lista confessadamente incompleta do que faz um bom commit.

Tamanho interessa sim

Bons commits são pequenos. Ponto.

Passar uma semana sem commitar e na sexta-feira fazer um braindump de tudo aquilo que se acumulou na sua máquina? Não é legal. Você deve de preferência commitar mais de uma vez ao dia, mas uma boa frequência mínima é de um commit por dia. São raras as instâncias em que você vai precisar de mais de um dia de trabalho dedicado para chegar a uma versão compilável e funcional do código que avança um pouco na direção da solução final.

Commits pequenos também ajudam seus companheiros de equipe. É muito mais fácil integrar a sua modificação em andamento com a minha modificação em andamento se cada alteração é bem focada em um único objetivo. Não tem coisa pior do que fazer uma integração “big bang” e ter que rememorar uma ou duas semanas de trabalho para explicar para seu colega qual era a intenção de alterar um trecho de código qualquer.

Revisões ficam mais fáceis também. Se você faz commits pequenos, o revisor pode facilmente acompanhar sua linha de raciocínio como se estivesse do seu lado quando você escreveu o código. As revisões futuras quando você tiver que conferir o histórico para caçar um bug qualquer também ficam mais fáceis. Isso nos leva ao nosso próximo ponto:

Deixe migalhas de pão para você mesmo

Esta é uma transcrição de um trecho do episódio 174 do podcast Ruby Rogues:

ERIC: Outra coisa que eu comecei a fazer recentemente é escrever bem mais nos meus commits e fazer commits bem menores. Algumas vezes eu revejo o histórico quando encontro um teste falhando e digo “Tá certo, porque essa linha está se comportando desse jeito?” E se for uma linha em um commit de 200 linhas com uma mensagem de commit de duas frases, não tem jeito de eu saber o que eu estaria pensando na hora em que modifiquei aquela linha, ou se era importante. Mas quando eu faço um commit de 10 ou 20 linhas e escrevo um parágrafo sobre ele, quando volto nele eu posso dizer “Isso é exatamente o que eu estava pensando quando escrevi isso.” Então tenho uma noção muito melhor de quais eram minhas idéias quando escrevi aquilo e porque aquela linha pode ser importante.

JAMES: Você aprendeu a ser legal com você mesmo.

ERIC: Sim.

[Risos]

JAMES: Isso é excelente. É algo em que todos nós podemos melhorar, concorda?

ERIC: É, deixar migalhas de pão para mim mesmo.

JAMES: Isso é muito bom.

ERIC: Eu me pego fazendo bastante leitura do histórico do código. e quando há mais commits no histórico, a leitura fica bem mais fácil do que “teve essa alteração aqui que tocou em todas as linhas. E agora eu tenho que dar um jeito de rastrear para descobrir para onde essa linha foi.” É super irritante para reproduzir o que você fez e o que você não fez. Quando tenho esses commits bonitos e pequenos, eu penso “Eu sei o que eu fiz” na mesma hora. Não leva 10 ou 15 minutos extras para refazer os passos e descobrir que commit é relevante e depois torcer para que tenha uma mensagem relevante.

Vamos encarar: cedo ou tarde você vai precisar ler o histórico do código. Seja para diagnosticar um caso em produção que a versão atual do código não poderia ter gerado de jeito nenhum ou para analisar a melhor solução para um bug.

Eu argumentaria até a favor de integrar a leitura do histórico no seu ferramental normal de resolução de bugs. Quando você detectar um bug ou quando chegar um relato de ocorrência em produção, tente rastrear que commit introduziu o bug e porque a pessoa fez isso. Com certeza ninguém colocou o bug lá de propósito, mas como efeito colateral de alguma outra alteração. Se começar a fazer isso, você vai passar a entender o que precisa fazer hoje para facilitar sua vida no futuro.

Nunca quebre o build

Nunca, mas nunca mesmo, em hipótese alguma, quebre o build.

E se quebrar, conserte rapidamente.

Seu código deve estar sempre minimamente compilando e com os testes rodando. Não estou falando aqui de nunca commitar bugs (até porque isso é impossível), mas de ter um padrão de qualidade mínimo dos seus commits. Não force os seus colegas de equipe a parar para corrigir esse tipo de erro primário que pode ser facilmente evitado apertando um botão no seu ambiente de desenvolvimento. Adquira o hábito de compilar e rodar os testes antes de apertar o botão de subir o código para o repo.

Isole modificações “de perfumaria”

Às vezes você está no meio de uma modificação e esbarra num comentário que está mostrando caracteres estranhos por algum erro de encoding. Ou então você nota que a tabulação está feita com hard tabs. Ou até mesmo encontra algum trecho de código que pode ser reduzido a uma única chamada se for usada uma função da biblioteca padrão.

Este tipo de alteração não vai mudar o comportamento do sistema, mas deve ser feito. Por outro lado, se você subir esta modificação junto com a sua, quem precisar ler o código vai ter uma carga cognitiva maior para conseguir entender o que você estava querendo fazer. Principalmente se você fez algum tipo de refactoring do código. Portanto, isole as modificações que não alteram o comportamento do sistema em seus próprios commits.

Você pode até combinar com sua equipe um padrão de título para commits de perfumaria. Assim quem precisar ler o histórico vai poder ignorar aquele commit em segurança, já que ele não afeta o comportamento do sistema.

Não repita o diff na mensagem de commit

Boas mensagens de commit são um assunto à parte. Mas a maioria das mensagens de commit seriam mais úteis se os devs atentassem para um fato simples: EU POSSO VER O DIFF! Então não precisa escrever na mensagem que aquele commit está acrescentando a rotina R à classe C.

A mensagem de commit serve para acrescentar informação ao diff, não para repeti-lo. O diff mostra o “o quê”, a mensagem deve ser usada para explicar o “porquê”. Eu consigo ver no diff que você acrescentou uma rotina R a uma classe C. O que eu preciso saber é porque diabos você acrescentou essa rotina. O que você estava pretendendo fazer com a nova rotina.

Revise sua alteração antes de subir

Nunca suba um commit antes de revisar o que está subindo. Sua IDE pode ter criado um arquivo de controle por trás dos panos… Você pode ter esquecido um print que estava usando para debug… O encoding dos arquivos de texto pode ter sido trocado acidentalmente… Milhões de coisas podem dar errado e fazer com que você suba lixo para o repo.

Além desses casos óbvios de lixo que você não quer que suba, há a questão semântica. Você pode querer criar vários commits para deixar mais explícita a evolução do código e/ou o raciocínio que usou para escrever aquilo.

Ferramentas atuais de controle de versão permitem que você separe facilmente os commits antes de subir (o git em especial é excelente nisso). É até aceitável que o primeiro dos commits quebre o build quando considerado isoladamente. Desde que seja uma alteração atômica e que suba para o repo junto com outros commits que o complementem e “consertem o build”.

Antes de publicar seu commit pense “Eu gostaria de revisar este commit numa sexta-feira à noite depois que todo mundo foi para casa e eu sou a última linha de defesa entre um bug e a aniquilação total da base de produção?”

One thought on “Anatomia de um bom commit

  1. Muito bom, realmente os commits mostram o quanto você se importa, já vi muitos casos de gente que faz um commit por feature(isso da nervoso só de ver).. Acho que o ritmo de commit tem que ser muito menor do que 1 dia. 20min de trabalho continuo sem um commit me parece um smell, na minha opinião commits são como funções: devem ter apenas um objetivo e fazer apenas uma coisa. Se você ver um repositório organizado com branchs de casa feature e commits pequenos o repositório parece um poema onde as branchs são estrofes e os commits são frases.. e no final te contam uma historia sem você precisar ler o código.

    Só a minha opinião é claro!

    Muito bom o texto. Abraço!

Comments are closed.