Semantic versioning com Git tags automatizadas
1. Fundamentos do Semantic Versioning (SemVer)
O Semantic Versioning (SemVer) é um padrão de versionamento que comunica o impacto de mudanças em software através de uma estrutura numérica de três partes: MAJOR.MINOR.PATCH. Cada componente segue regras rígidas de incremento:
- MAJOR: incrementado quando há mudanças incompatíveis com versões anteriores (breaking changes)
- MINOR: incrementado quando novas funcionalidades são adicionadas de forma compatível (novas features)
- PATCH: incrementado quando correções de bugs são feitas sem quebrar compatibilidade
Além disso, o SemVer permite sufixos opcionais para pré-release e metadados de build:
1.0.0-alpha.1+build.123
Onde -alpha.1 indica uma versão de pré-lançamento e +build.123 carrega metadados de compilação. Esses sufixos são ignorados na ordenação de versões estáveis.
2. Git Tags como Marcadores de Versão
Git tags são referências imutáveis que apontam para commits específicos. Existem dois tipos principais:
Lightweight tags: apenas um ponteiro para um commit, sem metadados adicionais.
Annotated tags: armazenam autor, data, mensagem e podem ser assinadas com GPG. São recomendadas para releases por serem objetos completos no repositório.
Criando e listando tags manualmente:
# Criar uma annotated tag
git tag -a v1.0.0 -m "Release v1.0.0"
# Listar tags existentes
git tag -l "v*"
# Compartilhar tags com o repositório remoto
git push origin v1.0.0
# Ou enviar todas as tags de uma vez
git push --tags
Boas práticas de nomenclatura incluem prefixo v (ex: v2.3.1) e consistência com o padrão SemVer.
3. Automação com Hooks e Scripts Locais
Hooks do Git permitem automatizar o versionamento localmente. Um script pós-commit pode extrair a mensagem do commit e decidir qual versão gerar.
Exemplo de script shell para incremento automático baseado no último commit:
#!/bin/bash
# post-commit hook - incrementa versão baseada no tipo de commit
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
VERSION=${LAST_TAG#v}
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
COMMIT_MSG=$(git log -1 --pretty=%B)
if echo "$COMMIT_MSG" | grep -qi "BREAKING CHANGE"; then
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
elif echo "$COMMIT_MSG" | grep -qi "^feat"; then
MINOR=$((MINOR + 1))
PATCH=0
elif echo "$COMMIT_MSG" | grep -qi "^fix"; then
PATCH=$((PATCH + 1))
else
exit 0
fi
NEW_TAG="v$MAJOR.$MINOR.$PATCH"
git tag -a "$NEW_TAG" -m "Release $NEW_TAG"
O comando git describe é particularmente útil para gerar versões baseadas em tags existentes:
git describe --tags --always --dirty
# Exemplo de saída: v1.2.3-5-gabc1234
Isso retorna a tag mais recente, o número de commits desde ela, o hash do commit e um sufixo -dirty se houver mudanças não commitadas.
4. Ferramentas de Automação de Versionamento
Ferramentas como standard-version e semantic-release automatizam o versionamento analisando mensagens de commit no padrão Conventional Commits.
Standard-version (Node.js):
npm install -g standard-version
# Executa análise de commits e gera nova tag automaticamente
standard-version
Semantic-release (mais complexo, integrado a CI/CD):
# Configuração no package.json
{
"release": {
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github"
]
}
}
As regras de bump seguem o padrão:
fix:→ incrementa PATCHfeat:→ incrementa MINORBREAKING CHANGE:no corpo do commit → incrementa MAJOR
Ambas as ferramentas geram automaticamente tags e changelogs, eliminando erros manuais.
5. Pipeline CI/CD com Tags Automatizadas
Em ambientes CI/CD, como GitHub Actions, é possível automatizar a criação de tags a partir de pushs em branches específicas.
Exemplo de workflow GitHub Actions:
name: Automated Versioning
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.name "github-actions"
git config user.email "actions@github.com"
npx semantic-release
Estratégias para evitar duplicação de tags:
- Utilizar
fetch-depth: 0para histórico completo - Verificar se a tag já existe antes de criar
- Usar tokens de acesso com permissões adequadas
- Implementar locks ou verificações de concorrência em pipelines paralelos
6. Gerenciamento de Versões em Repositórios Monorepo
Monorepos exigem versionamento independente por pacote. Tags prefixadas são a abordagem padrão:
@scope/package@1.2.3
Ferramentas especializadas facilitam esse processo:
Lerna:
lerna version --conventional-commits
Changesets (mais moderno):
npx changeset
npx changeset version
npx changeset tag
Ambas analisam mudanças em subdiretórios e geram tags múltiplas automaticamente. O versionamento atômico garante que todos os pacotes afetados sejam atualizados consistentemente.
7. Boas Práticas e Troubleshooting
Versionamento em branches de release vs. trunk-based:
Em trunk-based development, tags são criadas diretamente na branch principal após merge. Em branches de release, tags são criadas ao final do ciclo de estabilização.
Corrigindo tags incorretas:
# Remover tag local
git tag -d v1.0.0
# Remover tag remota
git push --delete origin v1.0.0
# Recriar a tag correta
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
Segurança com GPG:
Tags assinadas garantem autenticidade:
git tag -s v1.0.0 -m "Release v1.0.0"
git tag -v v1.0.0
Em pipelines, configure a verificação de assinatura:
git verify-tag v1.0.0
Isso impede que tags não autorizadas sejam usadas em releases oficiais, aumentando a segurança do processo.
Referências
- Semantic Versioning 2.0.0 Official Specification — Documentação oficial do padrão SemVer com especificações completas e exemplos
- Git SCM - Git Tagging Documentation — Documentação oficial do Git sobre criação e gerenciamento de tags
- Conventional Commits Specification — Especificação de mensagens de commit que automatizam versionamento semântico
- semantic-release GitHub Action — Ferramenta completa para automação de releases com análise de commits e geração de tags
- Changesets Documentation — Ferramenta para versionamento em monorepos com suporte a tags prefixadas e changelogs automáticos
- Lerna Version Command — Documentação oficial do Lerna para versionamento automático em repositórios com múltiplos pacotes
- GitHub Actions Workflow Syntax — Referência oficial para criação de workflows CI/CD com automação de tags