cd ..
CI/CD

Entendendo GitFlow, Pull Requests e proteção de branches

Quando trabalhamos sozinhos em um projeto pequeno, é comum realizar todas as alterações diretamente na branch principal.

O fluxo normalmente fica assim:

git add .
git commit -m "adiciona nova funcionalidade"
git push origin main

Esse processo pode funcionar em projetos pessoais, mas começa a apresentar problemas quando várias pessoas trabalham no mesmo repositório.

Imagine uma equipe em que:

Se todos enviarem alterações diretamente para a main, aumentam as chances de conflitos, falhas e código sem revisão chegar à produção.

Para organizar esse processo, podemos utilizar:

O que é GitFlow?

O GitFlow é um modelo de organização de branches no Git.

Ele define uma forma padronizada de separar o código que está em produção, o código que está sendo desenvolvido e as funcionalidades que ainda estão em construção.

No modelo tradicional, as principais branches são:

main
develop
feature
release
hotfix

Cada uma possui uma responsabilidade diferente.

Branch main

A branch main representa o código estável do projeto.

Normalmente, ela contém a versão que está pronta para produção ou que já está publicada.

main
└── versão estável do projeto

Por esse motivo, não é recomendado desenvolver funcionalidades diretamente nela.

A main deve receber apenas alterações que já foram:

Branch develop

A branch develop reúne as funcionalidades que estão sendo preparadas para a próxima versão.

develop
└── próxima versão do projeto

As diferentes branches de funcionalidades são integradas na develop.

Quando a próxima versão estiver estável, ela poderá seguir para uma branch de release ou ser integrada na main, dependendo do fluxo adotado pelo projeto.

Branches feature

As branches feature são utilizadas para desenvolver novas funcionalidades.

Por exemplo:

feature/login
feature/login-google
feature/cadastro-usuario

Cada funcionalidade é desenvolvida de forma isolada.

Isso permite que uma pessoa trabalhe na tela de login enquanto outra desenvolve o cadastro, sem que uma alteração interfira diretamente na outra.

Um fluxo comum seria:

develop
   └── feature/login

Depois que a funcionalidade estiver pronta, ela retorna para a develop por meio de um Pull Request.

Criando uma branch de funcionalidade

Primeiro, acessamos a branch de desenvolvimento:

git checkout develop

Atualizamos o código local:

git pull origin develop

Depois, criamos a nova branch:

git checkout -b feature/login

Também podemos utilizar o comando mais recente:

git switch -c feature/login

Após desenvolver a funcionalidade, adicionamos os arquivos:

git add .

Criamos o commit:

git commit -m "feat: adiciona tela de login"

E enviamos a branch para o repositório remoto:

git push -u origin feature/login

Agora a branch estará disponível no GitHub.

Branches release

As branches release são utilizadas para preparar uma nova versão do projeto.

Exemplo:

release/1.2.0

Nessa etapa, normalmente não são adicionadas grandes funcionalidades.

A branch é utilizada para:

Quando a versão estiver pronta, ela pode ser integrada na main.

Branches hotfix

As branches hotfix são utilizadas para corrigir problemas urgentes que já estão em produção.

Exemplo:

hotfix/corrigir-login

Como o problema está acontecendo na versão atual do sistema, a branch geralmente é criada a partir da main.

git checkout main
git pull origin main
git checkout -b hotfix/corrigir-login

Depois da correção:

git add .
git commit -m "fix: corrige erro no login"
git push -u origin hotfix/corrigir-login

A correção poderá ser integrada novamente na main e também na develop, evitando que o problema reapareça na próxima versão.

Visão geral do GitFlow

O fluxo pode ser representado da seguinte forma:

flowchart TD
    A[main] --> B[develop]
    B --> C[feature/login]
    B --> D[feature/cadastro]
    C --> B
    D --> B
    B --> E[release/1.0.0]
    E --> A
    A --> F[hotfix/corrigir-login]
    F --> A
    F --> B

A ideia principal é separar cada tipo de alteração.

main
└── código estável

develop
└── próxima versão

feature/*
└── novas funcionalidades

release/*
└── preparação de versões

hotfix/*
└── correções urgentes

O que é um Pull Request?

Um Pull Request, também conhecido como PR, é uma proposta para integrar as alterações de uma branch em outra.

Por exemplo:

feature/login → develop

Nesse caso, estamos propondo que o código desenvolvido na branch feature/login seja integrado na branch develop.

Em projetos que não utilizam a branch develop, o fluxo pode ser:

feature/login → main

O Pull Request cria uma etapa de revisão antes do merge.

Outras pessoas podem:

Criando um Pull Request

Depois de enviar a branch:

git push -u origin feature/login

Podemos abrir um Pull Request no GitHub.

Nesse Pull Request, escolhemos:

base: develop
compare: feature/login

Isso significa:

branch de destino: develop
branch de origem: feature/login

O título poderia ser:

feat: adiciona tela de login

E a descrição poderia explicar:

## O que foi desenvolvido?

Foi criada a tela de login da aplicação.

## Alterações

- criação do formulário;
- validação dos campos;
- integração com a API;
- tratamento de mensagens de erro.

## Como testar?

1. Execute a aplicação.
2. Acesse `/login`.
3. Informe um usuário válido.
4. Verifique o redirecionamento.

Uma boa descrição facilita bastante o trabalho de quem revisará o código.

Fluxo de um Pull Request

flowchart TD
    A[Desenvolver funcionalidade] --> B[Criar commits]
    B --> C[Enviar branch para o GitHub]
    C --> D[Abrir Pull Request]
    D --> E[Revisar o código]
    E --> F{Alterações necessárias?}
    F -- Sim --> G[Corrigir o código]
    G --> B
    F -- Não --> H[Aprovar Pull Request]
    H --> I[Realizar merge]

O Pull Request não é apenas um botão para juntar branches.

Ele também serve como:

O que é proteção de branches?

A proteção de branches é um conjunto de regras utilizado para impedir mudanças perigosas em branches importantes.

Normalmente, protegemos branches como:

main
develop

Sem uma regra de proteção, alguém poderia executar:

git push origin main

Isso permitiria enviar código diretamente para a branch principal, sem revisão e sem testes.

Em uma equipe, esse tipo de alteração pode quebrar a aplicação para todos.

Regras de proteção da branch

As regras de proteção podem exigir que:

Um fluxo protegido pode funcionar assim:

feature/login

Pull Request

Revisão do código

Testes automatizados

Aprovação

Merge na main

Por que proteger a main?

A branch principal representa a versão mais importante do repositório.

Se qualquer pessoa puder alterá-la diretamente, podem acontecer problemas como:

A proteção da branch transforma a main em uma área controlada.

Ninguém entra pela janela. Todo mundo passa pelo Pull Request.

Exemplo de regra para a main

Uma configuração comum pode exigir:

Exigir Pull Request antes do merge
Exigir pelo menos uma aprovação
Exigir que os testes passem
Exigir que os comentários sejam resolvidos
Bloquear push direto
Impedir exclusão da branch

Com isso, mesmo que alguém tente executar:

git push origin main

o GitHub poderá bloquear a operação.

O que é CODEOWNERS?

O arquivo CODEOWNERS permite definir responsáveis por diferentes partes do projeto.

Ele informa ao GitHub quem deve revisar uma alteração dependendo dos arquivos modificados.

Podemos entender sua função assim:

Quando alguém alterar esta parte do projeto, solicite a revisão destas pessoas.

O arquivo pode ser criado em:

.github/CODEOWNERS

Exemplo de CODEOWNERS

Imagine um projeto com esta estrutura:

frontend/
backend/
infra/
docs/
.github/

O arquivo poderia ser:

*                     @cesarsantos96
/frontend/            @dev-frontend
/backend/             @dev-backend
/infra/               @dev-infra
/docs/                 @cesarsantos96
/.github/              @cesarsantos96

Nesse exemplo:

Utilizando equipes no CODEOWNERS

Em uma organização do GitHub, também podemos utilizar equipes:

/frontend/     @empresa/time-frontend
/backend/      @empresa/time-backend
/infra/        @empresa/time-devops
/.github/      @empresa/time-devops

Assim, quando alguém alterar um arquivo dentro de backend, o GitHub poderá solicitar automaticamente a revisão do time responsável.

CODEOWNERS e proteção de branches

O CODEOWNERS fica ainda mais útil quando é utilizado junto com regras de proteção.

A regra pode exigir aprovação dos responsáveis definidos no arquivo.

O fluxo passa a funcionar assim:

flowchart TD
    A[Alteração no backend] --> B[Pull Request criado]
    B --> C[GitHub lê o CODEOWNERS]
    C --> D[Responsável pelo backend é solicitado]
    D --> E[Revisão do código]
    E --> F{Aprovado?}
    F -- Não --> G[Solicitar correções]
    F -- Sim --> H[Merge liberado]

Fluxo completo

Utilizando GitFlow, Pull Requests, proteção de branches e CODEOWNERS, o processo pode ficar assim:

flowchart TD
    A[Atualizar develop] --> B[Criar feature/login]
    B --> C[Desenvolver funcionalidade]
    C --> D[Criar commits]
    D --> E[Enviar branch para o GitHub]
    E --> F[Abrir Pull Request]
    F --> G[CODEOWNERS solicita revisores]
    F --> H[Testes automatizados]
    G --> I{Revisão aprovada?}
    H --> J{Testes passaram?}
    I -- Não --> K[Realizar correções]
    J -- Não --> K
    K --> D
    I -- Sim --> L[Validação final]
    J -- Sim --> L
    L --> M[Merge na branch protegida]

Cada ferramenta possui uma responsabilidade:

GitFlow
└── organiza as branches

Pull Request
└── organiza a revisão e a integração

Branch Protection
└── define regras obrigatórias

CODEOWNERS
└── define quem deve revisar

Conclusão

O GitFlow ajuda a organizar o desenvolvimento por meio de branches com responsabilidades diferentes.

As branches feature isolam novas funcionalidades. As branches release preparam novas versões, enquanto as branches hotfix corrigem problemas urgentes em produção.

Os Pull Requests criam uma etapa de revisão antes da integração do código.

As regras de proteção impedem alterações diretas em branches importantes, e o arquivo CODEOWNERS ajuda a encaminhar cada mudança para os responsáveis corretos.

Quando essas ferramentas são utilizadas em conjunto, o desenvolvimento se torna mais organizado, seguro e previsível.

O código deixa de seguir este caminho:

alteração → main

E passa a seguir um processo controlado:

branch → commit → Pull Request → revisão → testes → aprovação → merge

Referências

O que achou?