Boas práticas GIT para pessoas e times

30 dicas especiais para Cloud Engineers.

O Básico

1. Configure corretamente nome e e-mail

Para que seus commits não sejam gravados com autor “root” e-mail “root@root” configure esses valores iniciais assim que instalar seu GIT.

$ git config --global user.name "Nome Sobrenome"
$ git config --global user.email "email@domain.ext"

Pode acontecer de ter que mudar de e-mail dependendo do projeto, nesse caso rode isso dentro do diretório do seu projeto para sobrescrever as configurações globais

$ cd meu_projeto/
$ git config user.name "Nome Sobrenome"
$ git config user.email "email@domain.ext"

2. Configure seu editor favorito globalmente

Eu gosto de usar o VIM

 $ git config --global core.editor vim

3. Ative o autocorrect

O autocorrect vai te ajudar nos erros mais comuns, afinal quem nunca digitou git stats o bramch né?

$ git config --global help.autocorrect 10

olhe um exemplo quando digitamos BRAMCH ao invés de BRANCH

$ git bramch
WARNING: You called a Git command named 'bramch', which does not exist.
Continuing in 1.0 seconds, assuming that you meant 'branch'.
dev
prod
* main

olhe um exemplo quando digitamo STATS ao invés de STATUS

$ git stats
WARNING: You called a Git command named 'stats', which does not exist.
Continuing in 1.0 seconds, assuming that you meant 'status'.
On branch gh-pages
nothing to commit, working tree clean

É bastante útil não é?

O valor 10 declara 10x10 décimos de segundo, o mesmo que 1 segundo e por aí vai. Caso queira que corrija automaticamente sem aguardar, use o valor 1.

$ git config --global help.autocorrect 1

Dessa forma ele vai digitar o comando para você, veja mais detalhes no link abaixo

como desligar o autocorrect?

$ git config --global --unset help.autocorrect

4. Use uma versão atualizada do GIT

Normalmente o GIT que vem nas distribuições linux é bem antigo então é uma boa ideia atualizar se quer usar recursos mais recentes e versões com mais performance.

Se estiver no mac o Homebrew pode ajudar.

$ brew install git

Com isso você vai usar a última versão estável.

5. Crie aliases para agilizar seu trabalho

Atalhos para mais produtividade, o Git oferece aliases para que possamos economizar alguns caracteres, veja como usar

$ git config --global alias.co checkout
$ git co production
Switched to branch 'production'

outro exemplo

$ git config --global alias.st status
$ git st
On branch gh-pages
nothing to commit, working tree clean

Uma outra forma de criar aliases é editar seu gitconfig e setar manualmengte

$ vim ~/.gitconfig

Adicione uma sessão com essa

[alias]
    co = checkout
    st = status

Simples e rápido!

Junte seu time e defina os padrões que vão usar

Agora que seu GIT já está atualizado e configurado vamos definir algumas coisas.

6. Sente com seu time e formalize o padrão de versionamento que vão seguir

Combinar antes é sai mais barato do que arrumar depois, converse com seu time e defina:

  • Convenções comuns
  • Quais serão e como usar branchs de integração
  • Quais serão e como usar branchs de features
  • Quais serão e como usar demais branchs
  • Padrão de nome de branchs para integração
    • feature-xyz, hotfix-xyz, stage, test, prod
  • Padrão esperado para commit, forma, mensagens
  • Templates e forma de se fazer merge
  • Regras gerais do que se deve ou se deve não fazer

Eu sugiro que crie um repo git e coloque tudo isso em formato MD, nada melhor do que versionar suas regras :)

Boas práticas com branchs

7. Use e abuse de branchs

O recurso de branch é fantástico, você pode criar a partir de qualquer uma.

Dicas principais:

  • Evite gravar diretamente na main.
  • Sempre trabalhe em uma branch separada
  • Integre sua branch quando finalizar seu trabalho
  • Apague sua branch depois que tiver terminado

Exemplo

$ git branch -u main correcao_criacao_vpc
$ git checkout correcao_criacao_vpc

Quando terminar seu ticket, apague a branch

$ git branch -D correcao_criacao_vpc

8. Use branchs de integração

Quando estamos trabalhando com integração contínua o uso de branchs de integração é fundamental, precisamos integrar nosso código com o código de nossos colegas e rodar os testes na pipeline.

Geralmente temos uma branch de integração para desenvolvimento e depois vamos promovendo esse código para outras branchs que vão nos ajudar a fechar a release e publicar, tudo depende do git-flow que seu time acordou e está seguindo.

9. Não escreva direto na branch MAIN

Evitamos escrever direto na branch main pois geralmente é a última versão estável devidamente testada e validada por todos, é de fato a fonte da verdade, portanto, para colocar código lá devemos sempre passar por diversos testes em sua pipeline e revisões de seus colegas.

10. Mantenha sua feature-branch atualizada

Faça rebases regulares para garantir isso!

Exemplo de atualização da branch main localmente e depois rebase

$ git checkout main
$ git pull
$ git checkout feature-xyz  
$ git rebase main  

Exemplo de merge do código com a main

$ git checkout main
$ git pull
$ git merge feature-xyz

Hoje em dia eu quase não faço merge no braço, geralmente uso MR ou PR, depende da ferramenta que estamos usando.

11. De vez em quando recrie suas branchs de integração

Isso é legal de fazer para dar uma limpada na coisa toda e começar novamente.

$ git checkout main
$ git branch -D devel
$ git branch -u main devel

12. Limpe periodicamente branchs de feature

O ideal é sempre apagar suas branchs de feature ou de teste após finalizar um ticket.

Apesar de ser o ideal, nem sempre lembramos, então de vez em quando é bom olhar e apagar branchs que não estão sendo usadas.

Pode-se até definir um tempo de vida para branchs que não são fixas, e definindo isso podemos até criar uma automação para limpar o repo.

Boas práticas com commit

13. Corrija as mensagens do seu commit se errar

Caso perceba algum typo na sua mensagem de commit, use o amend para corrigir

 $ git commit -v --amend

14. Faça commits pontuais e objetivos

Evite fazer um commit com dezenas de arquivos, em especial se esses arquivos trazem mais de uma mudança ou correção. Devemos evitar isso pois fica difícil rastrear, entender e revisar o que foi feito no commit.

Prefira fazer commits pequenos e pontuais de algo que está terminado, algo que funciona e que não traga muitas alterações de uma vez só.

15. Faça commits atômicos quando possível

Já sabemos que commitar poucas alterações é o melhor caminho, mas dá para ser ainda menor.

Os commits atômicos são aqueles que gravam apenas uma única mudança – ainda que envolva vários arquivos – em um único commit.

É claro que nem sempre dá para fazer, mas é uma prática excelente se conseguir fazer.

A ideia do commit atômico é gravar a menor e mais importante melhoria que voce fez no código, sendo grande suficiente para adicionar algum valor, contudo, pequena o suficiente para ser gerenciada com flexibilidade.

Se quiser trabalhar dessa forma tenha em mente duas coisas:

  • Trabalhe em uma coisa por vez
  • Faça alterações pequenas e pontuais

16. Faça commits regulares e frequentes

Não espere demais!

Algumas pessoas esperam demais até gravar alguma alteração, às vezes ficam ali melhorando algo que já está funcionando, buscando algum tipo de perfeição antes de gravar.

Deixa eu te dizer uma coisa, o git funciona melhor e te ajuda mais quando você grava com frequência ao invés de esperar muitoooo tempo para gravar sua mudança.

Ao gravar com frequência você vai rastrear inclusive como você foi melhorando aquele código ao longo do seu processo e histórico de desenvolvimento.

E lembre-se, o GIT só cuida do seu código depois que você grava, se você fechar o editor por acidente ou se o editor travar, seu código já era, contudo, se estiver commitando com frequência você evita isso.

17. Quebre seu commit em commits menores

As vezes a gente vai trabalhando e se empolga demais, e com isso acaba fazendo mais de uma alteração em um mesmo arquivo, e neste caso, tais alteraçoes que poderiam ser commitadas de forma separada. Se for esse o caso, o commando abaixo te permite escolher quais mudanças você deseja commitar em um determinado arquivo.

$ git add -p <nome_do_arquivo>

Assim vamos conseguir commitar pequenas porções do arquivo por vez.

18. Não faça commit de algo que você não finalizou

Nunca, eu repito, nunca grave algo que não está funcionando ou que não está completo.

19. Teste seu código antes de gravar

Essa é uma das coisas mais básicas que vou falar hoje, mas tem que falar e tem que fazer.

Caso não saiba, gravar código quebrado é algo bastante incômodo, poderá irritar seus colegas, podendo em alguns casos chegar a ser considerado uma falta de respeito e falta de profissionalismo.

Verifique a sintaxe do seu código, rode um linter e execute o código para ver se o que fez está funcionando, seja uma feature, seja um bugfix, seja um hotfix, afinal, se o código estiver funcionando e se sua solução resolver o ticket, isso será o melhor dos mundos.

O git inclusive oferece um sistema de HOOKS que permite por exemplo, executar comandos de checagem antes de de gravar seu código, nesse caso estou falando do hook “pre-commit”, veja o link abaixo e leia sobre esse e outros hooks, é um recurso muito útil, acredite.

20. Escreva mensagens de commit claras

As mensagens precisam fazer sentido e ser úteis para todos do time.

20.1 Commitando em uma linha

A mensagem tem que fazer sentido, ser fácil de ler e ser suficiente para entender o que foi feito.

Exemplos

Podemos usar convenções para mostrar que fizemos uma correção

fix: corrige bug quando modulo vai crair a 2o VPC na AWS

ou uma refatoração

refact: refatora código que configura IAM para EKS na AWS

ou uma documentação

doc: adiciona docs para uso do modulo IAM/EKS

ou que inserimos testes

test: adiciona testes unitários no módulo
    

ou que criamos uma nova feature

feat: adiciona recurso para lidar com ALB no EC2/AWS
Entendendo a estrutura

É simples

feat: adiciona fature para recursos ALB no EC2/AWS #220412
^--^  ^-----------------------------------------^
|     |
|     +-> Sumário da sua mudança
|
+-------> Tipo: docs, feat, fix, refact, ou test.

Se você estiver usando um sistema de tickets junto, adicione o número do ticket na mensagem, sistemas como GitLab e GitHub já farão a associação para você entre a issue e o commit.

Evite colocar ponto final na mensagem, afinal é um título.

Vale lembrar que você deve evitar escrever mais de 50 caracteres ou vai quebrar a saída do “git log”.

De que modo escrever a mensagem?

Em alguns blogs vocês verão pessoas que defendam usar verbos no imperativo ou presente do indicativo, e faz sentido. Em ambos os casos a ideia é que o commit responda essa pergunta:

  "Em caso de aplicar esse commit ele..."

Resposta

...altera código X
...corrige módulo Y
...refatora manifesto Z
...cria feature W para módulo X

Eu já gosto de usar particípio do passado, pois foi algo que já foi realizado e nem precisa fazer a perguntinha para ver como tem que escrever, neste caso você pode afirmar ao invés de perguntar, dessa forma:

"Nesse commit foi..."

Resposta

...alterado código X
...corrigido módulo Y
...refatorado manifesto Z
...criada a feature W para módulo X

Enfim, existem longas threads sobre isso na internet, quase uma guerra santa, contudo, IMHO isso vai depender de cada um, ou da forma como cada time decidiu trabalhar.

No final o importante é você versionar seu código e conseguir entender o que fez ali lendo a mensagem de commit :)

20.2 Usando o editor para algo mais detalhado

As vezes precisamos escrever um pouco mais, indo além do “one line commit”, especialmente se foi uma correção complexa, se tem alguma pegadinha, ou se for preciso explicar porque você fez aquilo daquela forma. No caso do trabalho e o dia-a-dia dos Cloud Engineers nem sempre é necessário, mas se for, veja como fazer.

Nesse caso, como é uma mensagem longa, não podemos fazer “one line commit”, temos que ir para o editor.

$ git commit

E escrever a mensagem

Assunto da mensagem com no máximo 50 caracteres, sem ponto final

Descrição em múltiplas linhas
sobre seu commit. Use até 72 caracteres

Outros parágrafos podem vir após inserir 
uma linha em branco
Aqui nao tem mais limite de caracteres

Podemos usar bullets também, ajuda a organizar a informação

- Enumerando
- Alterações
- Realizadas
- Por
- Este
- Commit

Se existe um ticket coloque 
o número dele na mensagem e os tickets relacionados

Esse commit resolve o problema do ticket #2222
E está relacionado com o ticket #3333 e #4444

É bem simples!

21. Não reescreva o histórico da branch principal

Se você já gravou o código na branch principal, e o código alterado já está disponível para outras pessoas verem, recomenda-se não alterar esse histórico.

Fazer rebase na MAIN ou qualquer que seja o nome da sua branch upstream, ou mesmo em uma branch de integração pode causar problemas para seus colegas e eles podem ter que lidar com conflitos ou ter que fazer stash e baixar toda a branch novamente. Fora que normalmente alterações nessas branchs geralmente acionam gatilhos em ferramentas de CICD, o que pode gerar um deploy com regressão.

Dito isso, muito cuidado com suas branchs, em especial a upstream e as branchs de integração.

Na sua branch de feature você faz o que quiser, use o rebase sem problema algum, mas só nela ok?

Boas práticas com merge

22. Faça squash antes de fazer um merge

Antes de fazer um merge verifique seu histórico de commit, veja se é possível melhorar o histórico, reduzir e juntar algumas coisas, as vezes 20 commits podem ser agrupados em 10, fica mais limpo, organizado e facilitará a revisão por seus pares.

$ git rebase -i HEAD~20  # apresenta os últimos 20 commits para fazer o squash

Faça o squash na sua branch de trabalho antes de mandar o PR/MR e altere apenas os seus commits ok?

23. Use e abuse de MRs e PRs no GitHub e GitLab

A vantagem de usar PR ou MR seja no GitLab ou GitHub é que você tem facilidades para fazer squash, resolver conflitos, enxergar o que mudou (diff), solicitar revisão de pares, receber comentários e então finalmente fazer o merge. São excelentes recursos e devemos usá-los pois facilitam nossa vida.

Outras coisas interessantes

24. Use nomes consistentes para seus remotes

Origin é um nome padrão, mas não é obrigatório tá?

$ git push origin main

Podemos mudar esse nome para dar mais contexto e ficar mais claro de qual remote estamos falando

$ git push gitlab main
$ git push github main
$ git push bitbucket main
$ git push clienteX main

Colocar um contexto no nome do remote ajuda bastante, especialmente se tem vários remotes.

25. Prefira autenticação SSH ao invés de user/senha

Autenticação através de chaves é mais segura, tanto que algumas ferramentas como GitHub desabilitam push em outros métodos.

Criando uma chave ssh segura (ed2559)

Como criar um chave segura?

$ ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/nome_da_sua_chave -C “nome@domain.ext”

Quer saber por que usar o ed25519?

Basicamente pois é um algoritmo mais moderno que usa curvas elípiticas, mais performático comparado com outras alternativas.

Se quiser saber mais mergulhe nesse post!

Definindo o uso de chaves ssh para repos específicos

No meu caso eu trabalho com várias chaves ssh, uma para projetos pessoais, uma para projetos na empresa que trabalho e sempre crio chaves para projetos ou freelas que eu estou fazendo.

É sempre bom evitar usar a mesma chave para tudo.

Mas como organizar isso?

Simples edite o arquivo ~/.ssh/config e configure a chave para cada server

Host nativeltrail_gitlab
  Hostname gitlab.nativetrail.io
  User git
  IdentityFile ~/.ssh/id_ed2559_gitlab_nativetrail_key

Host client_x_gitlab
  Hostname gitlab.cliente-x.com
  User git
  IdentityFile ~/.ssh/id_ed2559_gitlab_clientex_key
  
Host gitlab
  Hostname gitlab.com
  User git
  IdentityFile ~/.ssh/id_ed2559_gitlab_key 

Host github
  Hostname github.com
  User git
  IdentityFile ~/.ssh/id_ed2559_github_key  

Pronto, diferentes chaves para diferentes servidores e serviços.

26. Use e abuse do .Gitignore

O Gitignore é um arquivo essencial em nosso repositório, é através dele que dizemos para o GIT ignorar alguns arquivos e não versioná-los.

O Github traz uma bela coleção de templates para isso, veja no link abaixo:

usando o gitignore local

neste caso crie na raiz do diretorio um arquivo com o nome .gitignore e insira o que deseja ignorar.

_site
_temp
_build
*.zip
*.tar.gz

e pronto, seu git vai ignorar esses padroes, saiba mais na documentação:

usando o gitignore global

Esse arquivo é global e todos os projetos vão ler ele, é bem útil para coisas comuns e para projetos que ainda não tem um .gitignore construído

Criando o arquivo

$ touch ~/caminho/para/seu/global/.gitignore

Ativando via CLI

$ git config --global core.excludesFile ~/caminho/para/seu/global/.gitignore

Caso prefira edite seu .gitconfig diretamente e insira a configuração

[core]
  excludesFile = ~/caminho/para/seu/global/.gitignore

No mac eu uso esse conteúdo

# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# Files that might appear on external disks
.Spotlight-V100
.Trashes

# Vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets

# Local History for Visual Studio Code
.history/

# Built Visual Studio Code Extensions
*.vsix

27. Use tags para criar referências no seu histórico

Tags que identificam milestones

$ git tag milestone-id -m
$ git push --tags

Tags que identificam um estado

$ git tag stable -m
$ git push --tags

Tags que identificam versões

$ git tag v1.2.3 -m
$ git push --tags

Existem várias formas de usar tags, seu uso facilita a identificação de um momento específico em seu histórico de desenvolvimento, tal como o fechamento de uma release, a conclusão de um milestones, a identifição e uma versão, o que possibilita que façamos clone do código naquele momento exato.

28. Se possível use versionamento semântico

Caso não conheça acessa o site https://semver.org

O versionamento semântico consiste basicamente no uso de três numeros que podem ser incrementados, como o exemplo abaixo:

2.3.5
MAJOR

O primeiro número é chamado de major, ele deve ser incrementando quando alguma mudança causa uma quebra de compatilidade de API

MINOR

O segundo número é chamado de minor, ele deve ser incrementado quando uma nova funcionalidade é adicionada, sem quebra de compatibilidade

PATCH

O terceiro número é chamado de patch, ele deve ser incrementado quando fazemos algum tipo de correção na versão minor

BUILD/RELEASE

Ao ler o semver.org você verá outras possibilidades de versionar, usando build number e release name, veja alguns exemplos:

1.0.0-alpha
1.0.0-beta
1.0.0-rc1
1.0.0-rc2
1.0.0+20130313144700
1.0.0-0.3.7

O versionamento semântico é bem flexível e fácil de usar, você vai ver.

Posso automatizar o incremento de versão?

Como as regras são claras fica fácil entender como incrementar a versões manualmente e podemos até mesmo automatizar isso em nossa pipeline.

Posso criar o meu próprio método?

Claro, cada time pode definir seu jeito de versionar, mas lembre-se criar um repo onde você explica isso para todo mundo, em formato MD. :)

29. Cuidado com Push usando FORCE

Quando você manda um

$ git push origin main --force

Você está sobrescrevendo tudo que tem no ORIGIN na branch MAIN.

Todo o cuidado é pouco, se for fazer avise a turma, peça permissão e faça um backup antes.

Quais problemas isso pode gerar?

Se alguém fez um push e você não atualizou sua branch local, os commits do coleginha serão perdidos.

Se alguém fez um clone e você mandou um force removendo várias coisas, no próximo pull o coleginha vai lidar com conflitos ou coisas piores, talvez tenha até que apagar o repo e baixar novamente.

Isso pode gerar algumas situações chatas com seu time, tome cuidado, use com cuidado.

30. Aprenda mais sobre o GIT e pratique

Aprender, entender e usar boas práticas vem com a experiência do dia a dia, quanto mais ler para conhecer seus recursos, quanto mais usar, mais precisará aprender, é assim que funciona.

Então vai lá e estuda!

Sucesso!

Refs

[s]
Guto

Se gostou manda um alo no twitter @gutocarvalho.