O que é versionamento de software e como ler números de versão

Três números separados por pontos carregam uma promessa. Em 4.18.2, o 4 diz “isto pode quebrar seu código se você vier da versão 3”, o 18 diz “há recursos novos, mas compatíveis” e o 2 diz “só correções”. Quem aprende a ler esses números entende, antes de atualizar, o tamanho do risco.
$ ls ./neste-artigo
- Como o SemVer divide MAJOR, MINOR e PATCH
- Sintoma: “atualizei uma biblioteca e o projeto parou de compilar”
- Sintoma: “na minha máquina funciona, no servidor quebrou”
- Sintoma: “era só um MINOR e mesmo assim quebrou”
- Sintoma: “a biblioteca está na 0.x e cada atualização muda tudo”
- Sintoma: “o alerta de segurança pede uma versão que eu não sei se posso instalar”
- Nem todo projeto usa SemVer, e tudo bem
- Versionando o seu próprio projeto
Versionamento de software é a prática de dar a cada estado publicado de um programa um identificador único, de forma que usuários, equipes e ferramentas saibam exatamente o que estão usando. A convenção mais adotada para isso é o versionamento semântico, ou SemVer. E a maior parte dos problemas que iniciantes enfrentam com dependências nasce de ler esses números errado.
Como o SemVer divide MAJOR, MINOR e PATCH
A especificação oficial do Versionamento Semântico 2.0.0 define o formato MAJOR.MINOR.PATCH e as regras para incrementar cada parte:
| Parte | Sobe quando | Exemplo | Risco ao atualizar |
|---|---|---|---|
| MAJOR | Há mudança incompatível na API pública | 2.9.4 → 3.0.0 | Alto: leia as notas da versão |
| MINOR | Entra funcionalidade nova, compatível | 2.9.4 → 2.10.0 | Baixo, em tese |
| PATCH | Só correção de bug compatível | 2.9.4 → 2.9.5 | Muito baixo, em tese |
Um exemplo real de leitura: o seu projeto usa uma biblioteca de datas na 2.29.4 e aparecem três atualizações disponíveis, 2.29.5, 2.30.0 e 3.0.0. A primeira corrige bugs e pode entrar hoje. A segunda traz funções novas sem quebrar as antigas; entra depois de rodar os testes. A terceira pede leitura das notas de versão, uma branch separada e tempo reservado na sprint. Três números, três níveis de cuidado.
Repare que 2.10.0 vem depois de 2.9.0. Não é número decimal: cada parte é um inteiro independente. Ordenar versões como texto (“2.10” antes de “2.9”) é um bug clássico em scripts caseiros.
Quando MAJOR sobe, MINOR e PATCH voltam a zero. Quando MINOR sobe, PATCH zera. E existem rótulos de pré-lançamento, como 3.0.0-beta.2 ou 3.0.0-rc.1, que indicam versões ainda não estáveis e vêm antes da 3.0.0 final na ordem.
Sintoma: “atualizei uma biblioteca e o projeto parou de compilar”
Causa mais provável: você atravessou um MAJOR. Algum método foi renomeado, removido ou mudou de assinatura.
Correção: veja o salto no package.json, requirements.txt ou equivalente. Se foi de 4.x para 5.x, procure o guia de migração no repositório da biblioteca (normalmente um arquivo CHANGELOG ou uma página “Migrating to v5”). Atualize um MAJOR por vez, nunca três dependências grandes de uma vez, para saber qual quebrou o quê.
Sintoma: “na minha máquina funciona, no servidor quebrou”
Origem do problema: as duas máquinas instalaram versões diferentes da mesma dependência, porque o projeto declara uma faixa e não uma versão exata.
No npm, os símbolos na frente da versão definem a faixa aceita, como explica a documentação do npm sobre versionamento semântico:
"express": "4.18.2" // exatamente esta
"express": "~4.18.2" // aceita 4.18.x (só PATCH)
"express": "^4.18.2" // aceita 4.x.x a partir de 4.18.2 (MINOR e PATCH)O que fazer: commitar o arquivo de trava (package-lock.json, yarn.lock, poetry.lock) e, no servidor e no CI, instalar com o comando que respeita a trava, como npm ci em vez de npm install. O lockfile registra a versão exata que você testou; sem ele, o “^” deixa a próxima instalação pegar uma versão mais nova.

Sintoma: “era só um MINOR e mesmo assim quebrou”
Por que acontece: o SemVer é uma promessa do autor, não uma garantia técnica. Um mantenedor pode, por descuido, mudar um comportamento num MINOR. Ou o seu código dependia de algo que não fazia parte da API pública (um bug que você usava como recurso, por exemplo).
Saída prática: reporte o problema no repositório da biblioteca, fixe temporariamente a versão anterior e rode a suíte de testes antes de qualquer atualização. Ferramentas como Dependabot e Renovate abrem pull requests de atualização um a um justamente para que os testes do CI peguem isso.
Sintoma: “a biblioteca está na 0.x e cada atualização muda tudo”
Causa: pela especificação, MAJOR zero significa desenvolvimento inicial, e qualquer coisa pode mudar a qualquer momento. Uma biblioteca em 0.14.0 não promete estabilidade.
O npm já trata isso de forma diferente: ^0.14.2 aceita apenas 0.14.x, e não 0.15.0, porque nessa fase o MINOR costuma carregar mudanças incompatíveis. Muita gente não sabe disso e estranha que o “^” pareça “travar” a atualização.
Na prática: trate cada MINOR de uma 0.x como se fosse um MAJOR. Leia as notas antes.
Sintoma: “o alerta de segurança pede uma versão que eu não sei se posso instalar”
Motivo: avisos de vulnerabilidade costumam dizer algo como “afetadas as versões anteriores a 3.4.7”. Se você está na 3.2.1, a correção está dentro do mesmo MAJOR e, pela promessa do SemVer, deve ser segura de aplicar. Se está na 2.x, a correção pode existir só na linha 3.x, e aí a atualização de segurança vira uma migração.
Caminho seguro: veja se o projeto publica correções para linhas antigas (muitos mantêm a versão principal anterior por um tempo). Se não publicar, planeje a migração de MAJOR em vez de adiar indefinidamente. Rodar npm audit ou pip-audit mostra rapidamente quais dependências estão nessa situação.
Ficar parado numa versão antiga não elimina o risco de atualizar. Só troca o risco de quebrar hoje pelo risco de ser invadido amanhã.
Nem todo projeto usa SemVer, e tudo bem
Alguns softwares adotam versionamento por calendário (CalVer): o Ubuntu 24.04 saiu em abril de 2024. O Python segue suas próprias regras, documentadas na PEP 440, e o Node.js alterna versões pares de suporte longo (LTS) com ímpares de curta duração. Navegadores apenas incrementam um número grande a cada ciclo.
Antes de supor o significado de um número, veja que convenção o projeto declara. Um bom exemplo de leitura cuidadosa de versões é o texto do buildbase sobre como migrar para o Node.js 26 LTS, que mostra o que muda de uma versão principal para a outra.
Versionando o seu próprio projeto

Quando for você a publicar, três hábitos resolvem quase tudo:
- marque cada versão publicada com uma tag no Git (git tag -a v1.4.0 -m “versão 1.4.0”), conforme a referência do git tag;
- mantenha um arquivo CHANGELOG com o que entrou, mudou e foi corrigido em cada versão;
- decida o número pelo impacto para quem usa, não pelo tamanho do trabalho: um mês de refatoração interna sem mudar a API é um PATCH.
Para quem publica bibliotecas, há ainda a versão 1.0.0, que merece cerimônia: ela declara que a API pública está estável e que, dali em diante, quebrar compatibilidade custa um MAJOR. Muitos projetos ficam anos na 0.x por receio de assumir esse compromisso, e isso deixa quem depende deles sem garantia nenhuma.
O último ponto confunde muita gente. A versão comunica efeito, não esforço. Remover um parâmetro opcional que ninguém usava ainda é, tecnicamente, uma mudança incompatível, e pede MAJOR.
Para outros termos que surgem nesse assunto, como tag, lockfile e release, consulte o glossário de programação do buildbase. E, da próxima vez que um número de versão mudar no seu projeto, olhe primeiro qual das três partes subiu: isso já diz quanto cuidado a atualização pede.




