Fork e o modelo de contribuição open source

1. O que é um Fork e por que ele é essencial no open source

No contexto do Git e de plataformas como GitHub e GitLab, um fork é uma cópia completa de um repositório que fica sob sua conta pessoal. Diferente de um clone, que cria uma cópia local no seu computador, o fork é um repositório remoto independente que você controla totalmente.

A principal diferença entre fork e clone é:
- Clone: cópia local do repositório, com conexão direta ao original (remote origin).
- Fork: cópia remota do repositório em sua conta, permitindo que você faça push de alterações sem permissão de escrita no repositório original.

O fork é essencial no open source porque:
- Você não precisa de permissão de push para contribuir.
- O mantenedor do projeto original mantém controle total sobre o que é incorporado.
- Cada contribuidor trabalha em seu próprio espaço isolado.

2. Fluxo de trabalho básico: do fork ao Pull Request

O ciclo completo de contribuição via fork segue estas etapas:

# 1. Faça o fork do repositório no GitHub/GitLab (via interface web)

# 2. Clone seu fork localmente
git clone https://github.com/seu-usuario/repositorio-fork.git
cd repositorio-fork

# 3. Configure o remote upstream (repositório original)
git remote add upstream https://github.com/usuario-original/repositorio.git

# 4. Crie uma branch para sua contribuição
git checkout -b feature/minha-melhoria

# 5. Faça as alterações e commit
git add .
git commit -m "Adiciona nova funcionalidade X"

# 6. Envie para seu fork
git push origin feature/minha-melhoria

# 7. No GitHub/GitLab, abra um Pull Request da sua branch para o repositório original

3. Sincronizando seu fork com o repositório original

Manter seu fork atualizado é crucial para evitar conflitos. Existem duas abordagens principais:

Usando merge (mais simples)

# Buscar as últimas alterações do upstream
git fetch upstream

# Mudar para a branch main local
git checkout main

# Incorporar as alterações do upstream
git merge upstream/main

# Atualizar seu fork remoto
git push origin main

Usando rebase (histórico mais limpo)

git fetch upstream
git checkout main
git rebase upstream/main
git push origin main --force-with-lease

O --force-with-lease é mais seguro que --force, pois protege contra sobrescrita acidental de commits de outros contribuidores no seu fork.

Resolvendo conflitos ao sincronizar

Se houver conflitos durante o merge ou rebase:

# Durante um merge, resolva os conflitos manualmente, depois:
git add .
git commit -m "Resolve conflitos com upstream"

# Durante um rebase, resolva os conflitos, depois:
git add .
git rebase --continue

4. Criando branches de contribuição e boas práticas

Sempre trabalhe em branches separadas, nunca diretamente no main:

# Boas práticas de nomenclatura
git checkout -b feature/adiciona-autenticacao
git checkout -b fix/corrige-bug-login-123
git checkout -b docs/atualiza-readme
git checkout -b refactor/otimiza-consulta-sql

Mantenha sua branch main sempre limpa, usada apenas para sincronização com o upstream. Isso facilita:
- Criar novas branches a partir de um estado atualizado.
- Evitar conflitos desnecessários.
- Poder deletar forks sem perder trabalho.

5. Abrindo um Pull Request a partir do fork

A principal diferença entre PR de fork e PR interno é que o mantenedor não pode fazer push diretamente na sua branch. Portanto, a descrição do PR deve ser mais detalhada.

Um bom template para descrição de PR:

## Contexto
Este PR resolve o problema #42 onde o sistema não tratava corretamente...

## Alterações realizadas
- Adiciona validação de email no formulário de login
- Corrige bug na função de hash de senha
- Atualiza testes unitários

## Testes realizados
- Testes manuais com emails inválidos
- Suite de testes existente: 100% passando
- Teste de integração com banco de dados

## Como testar
1. Faça checkout da branch `fix/validacao-email`
2. Execute `npm test`
3. Tente cadastrar com email "invalido"

Para vincular issues, use palavras-chave no corpo do PR:

Closes #42
Related to #15

6. Lidando com feedback e revisão de código

Quando o revisor solicitar alterações, você atualiza o mesmo PR com novos commits:

# Na mesma branch do PR
git checkout feature/minha-melhoria

# Faça as alterações solicitadas
git add .
git commit -m "Corrige validação conforme review"

# Envie para o fork (atualiza o PR automaticamente)
git push origin feature/minha-melhoria

Squashing commits com rebase interativo

Para manter o histórico limpo antes do merge:

# Squash os últimos 3 commits em 1
git rebase -i HEAD~3

# No editor, troque 'pick' por 'squash' nos commits secundários
# pick 1a2b3c Primeiro commit
# squash 4d5e6f Segundo commit
# squash 7g8h9i Terceiro commit

# Após salvar, force push no fork
git push origin feature/minha-melhoria --force-with-lease

Cuidado com force push: use --force-with-lease em vez de --force para evitar sobrescrever alterações de outros colaboradores no mesmo fork.

7. Manutenção do fork a longo prazo

Quando deletar o fork

Após seu PR ser aceito e mergeado:
- Você pode deletar o fork se não planeja mais contribuir.
- Mantenha se pretende fazer contribuições futuras.
- Remova branches antigas para organização:

# Deletar branch local
git branch -d feature/minha-melhoria

# Deletar branch remota no fork
git push origin --delete feature/minha-melhoria

Estratégias para múltiplos forks

Se você contribui para vários projetos ou mantém múltiplos forks do mesmo repositório:
- Use nomes de diretórios diferentes localmente.
- Configure remotes específicos para cada fork.
- Considere usar ferramentas como gh (GitHub CLI) para gerenciar forks.

Evitando divergência excessiva

Para evitar que seu fork fique muito diferente do upstream:
- Sincronize regularmente (semanalmente ou antes de cada contribuição).
- Nunca trabalhe diretamente no main do fork.
- Use branches de curta duração para cada contribuição.

Se seu fork divergiu muito, considere criar um novo fork em vez de tentar resolver conflitos complexos.

Referências