Hotfix workflow: corrigindo produção sem quebrar develop
1. O problema clássico: produção pegando fogo e develop instável
Todo desenvolvedor já viveu o pesadelo: um bug crítico é reportado em produção, mas o branch develop está repleto de features incompletas, refatorações arriscadas ou código que ainda não passou por testes de integração. O dilema é imediato — corrigir o problema sem arrastar para produção todo o trabalho em andamento que pode introduzir novos bugs.
O erro mais comum é tentar aplicar o hotfix diretamente em main (ou master) e esperar que tudo se resolva. Isso raramente funciona, porque o histórico de main pode estar defasado em relação a develop, e um merge direto pode trazer alterações indesejadas. Pior ainda: se o hotfix precisar reverter alguma lógica introduzida em develop, o conflito será inevitável e custoso.
Exemplo concreto: suponha que develop tenha uma nova regra de validação de e-mail que quebra um fluxo de cadastro. O hotfix precisa desabilitar temporariamente essa validação em produção. Se você fizer merge direto de develop em main, estará trazendo a validação problemática de volta. Se fizer cherry-pick do hotfix, perde a rastreabilidade. A solução é um workflow estruturado.
2. Estrutura de branches para hotfix: o modelo Git Flow adaptado
O Git Flow oferece um padrão maduro para lidar com correções urgentes. A ideia central é criar um branch hotfix/ a partir do ponto exato onde a produção está — ou seja, de main.
git checkout main
git pull origin main
git checkout -b hotfix/1.2.1-corrige-crash-usuarios
Esse branch é temporário e deve viver apenas o tempo necessário para aplicar a correção, testar e fazer os merges nos dois destinos: main (produção) e develop (desenvolvimento contínuo).
A diferença fundamental entre hotfix/ e bugfix/ é o alvo: hotfix/ sempre parte de main e visa produção; bugfix/ parte de develop e visa o ciclo normal de desenvolvimento. A nomenclatura semântica ajuda na organização:
hotfix/<versão-alvo>-<descrição-curta>
# Exemplo: hotfix/1.2.1-corrige-crash-usuarios
3. Criando e aplicando a correção no branch hotfix
O princípio é isolamento máximo. A correção deve ser mínima, focada exclusivamente no bug reportado. Nada de refatorações, melhorias de performance ou ajustes de estilo.
# Aplicar a correção nos arquivos necessários
git add src/controllers/user.js src/utils/validation.js
git commit -m "fix: corrige crash ao carregar lista de usuários com campo nulo"
A mensagem de commit deve seguir um padrão reconhecível, como Conventional Commits. Isso facilita a geração automática de changelog e a rastreabilidade.
Após o commit, é boa prática criar uma tag semântica para marcar a versão corrigida:
git tag -a v1.2.1 -m "Hotfix: correção de segurança no fluxo de usuários"
git push origin hotfix/1.2.1-corrige-crash-usuarios --tags
4. Merge do hotfix em main (produção) — sem surpresas
Com o hotfix testado localmente, o próximo passo é integrá-lo à produção. O merge deve ser feito com --no-ff para preservar o histórico de que aquele branch foi criado especificamente para uma correção urgente.
git checkout main
git pull origin main
git merge --no-ff hotfix/1.2.1-corrige-crash-usuarios
git push origin main
A partir desse ponto, o deploy pode ser disparado — seja manualmente ou via pipeline de CI/CD. Recomenda-se usar a tag v1.2.1 como referência para o deploy, garantindo que exatamente aquela versão corrigida vá para produção.
Após o deploy, execute smoke tests básicos ou um canary release para verificar se a correção não introduziu efeitos colaterais.
5. Sincronizando o hotfix de volta para develop — o ponto crítico
Este é o passo que muitos ignoram e que causa mais retrabalho. O hotfix precisa ser incorporado também ao branch develop, para que o próximo release contenha a correção. Existem duas estratégias principais:
Estratégia 1: merge direto do hotfix em develop
git checkout develop
git pull origin develop
git merge --no-ff hotfix/1.2.1-corrige-crash-usuarios
Simples, mas perigosa. Se develop tiver refatorado os mesmos arquivos do hotfix, os conflitos podem ser complexos e exigir entendimento profundo do contexto.
Estratégia 2: merge de main em develop (recomendada)
git checkout develop
git pull origin develop
git merge main
Essa abordagem é mais segura porque o merge de main em develop traz todo o histórico linear da correção, e conflitos tendem a ser mais previsíveis — afinal, main só contém o hotfix e nada mais. Além disso, mantém a rastreabilidade: qualquer pessoa que olhar o histórico de develop saberá que aquela correção veio de main.
6. Quando o hotfix conflita com features em desenvolvimento
Conflitos acontecem. O hotfix pode alterar uma função que foi completamente reescrita em develop. Para identificar esses pontos antecipadamente:
git log develop..main --oneline
git merge-tree $(git merge-base develop main) develop main
O segundo comando simula o merge sem alterar o repositório, mostrando onde haveria conflitos.
A resolução manual exige cuidado: entenda o que cada alteração faz. O hotfix geralmente é uma correção pontual; a feature em develop pode ter mudado a arquitetura. Nesse caso, a solução é aplicar a lógica do hotfix dentro do novo código da feature.
Uma alternativa segura é criar um branch intermediário:
git checkout develop
git checkout -b merge-hotfix-into-develop
git merge main
# Resolver conflitos aqui
git commit -m "merge: integra hotfix v1.2.1 em develop"
git push origin merge-hotfix-into-develop
Depois de revisado, esse branch é mergeado em develop com --no-ff.
7. Automação e boas práticas para evitar retrabalho
Um script simples pode padronizar o fluxo e evitar erros manuais:
#!/bin/bash
# hotfix-start.sh
VERSION=$1
DESCRIPTION=$2
git checkout main
git pull
git checkout -b hotfix/$VERSION-$DESCRIPTION
echo "Branch hotfix/$VERSION-$DESCRIPTION criado a partir de main"
Para o merge duplo, um script de CI pode ser configurado. Exemplo com GitHub Actions:
# .github/workflows/hotfix.yml
on:
push:
branches:
- hotfix/*
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
- run: npm run lint
merge-main:
needs: validate
runs-on: ubuntu-latest
steps:
- run: git checkout main && git merge --no-ff ${{ github.ref }} && git push
merge-develop:
needs: validate
runs-on: ubuntu-latest
steps:
- run: git checkout develop && git merge main && git push
Checklist antes de qualquer merge de hotfix:
- [ ] Testes unitários passando
- [ ] Lint sem erros
- [ ] Changelog atualizado
- [ ] Tag semântica criada
8. Estudo de caso: hotfix real com rollback e sincronização
Cenário: Após o deploy da versão v1.2.0, usuários reportam que o sistema de login está lançando exceção quando o campo "telefone" é nulo. O bug foi introduzido por uma validação nova que ainda não estava em develop.
Passo a passo:
# 1. Criar branch hotfix a partir de main
git checkout main
git checkout -b hotfix/1.2.1-corrige-login-telefone-nulo
# 2. Aplicar correção
# Editar src/auth/validation.js
git add src/auth/validation.js
git commit -m "fix: permite campo telefone nulo no login"
# 3. Taggear
git tag -a v1.2.1 -m "Hotfix: login com telefone nulo"
# 4. Merge em main e deploy
git checkout main
git merge --no-ff hotfix/1.2.1-corrige-login-telefone-nulo
git push origin main --tags
# 5. Sincronizar develop
git checkout develop
git merge main
# Sem conflitos, pois develop não alterou auth/validation.js
git push origin develop
# 6. Limpeza
git branch -d hotfix/1.2.1-corrige-login-telefone-nulo
Lições aprendidas:
- Nunca faça cherry-pick isolado de um hotfix para develop — você perde a relação com a tag e o histórico.
- Mantenha o hotfix o mais enxuto possível; qualquer linha extra é risco.
- Automatize o merge duplo para evitar esquecimentos.
O hotfix workflow, quando bem executado, permite corrigir produção em minutos sem comprometer o ciclo de desenvolvimento. A chave está em respeitar a separação de branches, usar merges com --no-ff e sempre sincronizar a correção de volta para develop.
Referências
- Git Flow — Documentação Oficial (nvie) — Artigo seminal que define o modelo de branching com branches hotfix, develop e main.
- Atlassian: Git Hotfix Workflow — Tutorial prático da Atlassian sobre como criar e gerenciar hotfix branches no Git Flow.
- GitHub Docs: Gerenciando branches de hotfix — Guia oficial do GitHub sobre workflows de hotfix com exemplos de comandos.
- Conventional Commits — Especificação para mensagens de commit padronizadas, útil para identificar hotfixes em changelogs automatizados.
- Git SCM: git-merge-tree — Documentação oficial do comando
git merge-treepara simular merges e identificar conflitos antes de executá-los.