Como usar git notes para anotar commits sem modificá-los

1. Introdução ao git notes: o que são e por que usá-los

O git notes é um recurso poderoso e frequentemente subestimado do Git que permite adicionar anotações a commits sem alterar seu conteúdo original. Diferentemente de uma mensagem de commit tradicional, que fica gravada permanentemente no histórico do repositório, as notas são armazenadas separadamente, em referências especiais (refs/notes/). Isso significa que você pode enriquecer commits com informações contextuais, metadados extras ou comentários de revisão sem modificar o hash, autor, data ou mensagem do commit original.

A principal diferença entre git notes e mensagens de commit é que as notas são voláteis e independentes. Enquanto uma mensagem de commit é imutável após a criação (a menos que você reescreva o histórico com git commit --amend ou git rebase), as notas podem ser adicionadas, editadas e removidas a qualquer momento, sem afetar a integridade do histórico.

Casos de uso comuns incluem:
- Revisão de código: anotar commits com feedback de revisores sem poluir as mensagens originais.
- Auditoria: registrar informações de conformidade, como aprovações de segurança ou rastreamento de requisitos.
- Metadados extras: armazenar links para issues, pull requests, logs de build ou resultados de testes automatizados.
- Documentação pós-fato: adicionar contexto a commits antigos que carecem de explicação detalhada.

2. Comandos básicos para criar e visualizar notas

O comando fundamental é git notes add, que associa uma nota a um commit específico. Se nenhum commit for informado, o HEAD é usado por padrão.

# Adicionar uma nota ao commit atual
git notes add -m "Nota: revisão pendente do módulo de autenticação"

# Adicionar uma nota a um commit específico (pelo hash)
git notes add -m "Bugfix confirmado em ambiente de staging" a1b2c3d

Para visualizar as notas, use git notes list para listar todos os commits que possuem notas, e git notes show para exibir o conteúdo de uma nota específica.

# Listar commits com notas
git notes list

# Exibir a nota de um commit específico
git notes show a1b2c3d

# Exibir notas junto com o log
git log --show-notes

Exemplo prático: suponha que você tenha um commit de bugfix com hash f6e7d8c. Você pode anotá-lo com contexto adicional para sua equipe:

git notes add -m "Correção aplicada após análise de logs do servidor de produção. 
O erro ocorria devido a uma race condition na validação de tokens JWT.
Testes unitários adicionados no módulo auth.test.js" f6e7d8c

3. Gerenciando múltiplas notas por commit com namespaces

Por padrão, as notas são armazenadas em refs/notes/commits. No entanto, você pode criar namespaces personalizados para organizar diferentes tipos de anotações. Isso é especialmente útil em equipes grandes, onde diferentes papéis (revisão, QA, segurança) precisam de espaços separados.

# Criar uma nota no namespace 'review'
git notes --ref=review add -m "Código revisado e aprovado. Pontos de atenção: 
- Verificar performance em queries grandes
- OK para merge" a1b2c3d

# Criar uma nota no namespace 'ci-status'
git notes --ref=ci-status add -m "Pipeline passou: 
- Testes unitários: 142/142 passaram
- Lint: sem erros
- Cobertura: 87%" b2c3d4e

Para visualizar notas de um namespace específico:

# Mostrar nota do namespace 'review' para um commit
git notes --ref=review show a1b2c3d

# Listar todos os commits com notas no namespace 'review'
git notes --ref=review list

4. Editando, removendo e copiando notas entre commits

A edição de notas é feita com git notes edit, que abre o editor padrão do sistema. Para remover, use git notes remove. A cópia de notas entre commits é útil quando você quer replicar informações contextuais.

# Editar uma nota existente (abre o editor)
git notes edit a1b2c3d

# Remover uma nota
git notes remove a1b2c3d

# Copiar nota de um commit para outro
git notes copy a1b2c3d d4e5f6g

Atenção: ao copiar notas, você pode especificar o namespace de origem e destino:

git notes copy --ref=review a1b2c3d --ref=review d4e5f6g

5. Compartilhando notas com a equipe via push e pull

Por padrão, git push e git pull não transferem notas. Para compartilhá-las com sua equipe, você precisa explicitamente enviar e baixar as referências de notas.

# Enviar todas as notas para o remoto
git push origin refs/notes/*

# Baixar notas de outros colaboradores
git fetch origin refs/notes/*:refs/notes/*

Boas práticas: crie aliases no Git para simplificar a sincronização:

git config --global alias.push-notes "push origin refs/notes/*"
git config --global alias.fetch-notes "fetch origin refs/notes/*:refs/notes/*"

Você também pode configurar hooks (post-commit, post-merge) para automatizar o push de notas após cada commit ou merge.

6. Integração com ferramentas de revisão e CI/CD

As notas são ideais para armazenar resultados de processos automatizados sem poluir o histórico. Exemplo: um script de CI que adiciona uma nota com o status da build.

#!/bin/bash
# Script: add-ci-note.sh
COMMIT_HASH=$1
BUILD_STATUS=$2
TEST_RESULTS=$3

git notes --ref=ci-status add -m "Build: $BUILD_STATUS
Testes: $TEST_RESULTS
Data: $(date)" $COMMIT_HASH

git push origin refs/notes/ci-status

Exemplo prático: anotar commits com links para issues ou pull requests:

git notes add -m "Issue relacionada: https://github.com/meuprojeto/issues/42
PR de revisão: https://github.com/meuprojeto/pull/128
Log de build: https://ci.meuprojeto.com/builds/8910" f6e7d8c

7. Boas práticas e armadilhas comuns

Cuidados importantes:

  1. Notas órfãs após rebase ou squash: ao reescrever o histórico com git rebase ou git commit --squash, as notas originais podem ficar órfãs (associadas a commits que não existem mais). Use git notes --ref=review prune para removê-las.

  2. Limpeza periódica: crie um script que execute git notes prune regularmente para eliminar notas de commits removidos.

  3. Consistência em equipes grandes: defina convenções claras para nomes de namespace e formato das notas. Exemplo:

  4. review: feedback de revisão de código
  5. qa: resultados de testes manuais
  6. security: aprovações de segurança
  7. ci-status: resultados de pipelines automatizados

  8. Evite informações sensíveis: notas são armazenadas em texto plano. Não inclua senhas, tokens ou dados pessoais.

  9. Documentação: inclua no README do repositório as convenções de notas adotadas pela equipe.


Referências