# Aula 3.5 - Git, branches e pull requests

## Identificação

- **Duração:** 2 horas
- **Tipo:** teoria aplicada e laboratório
- **Entrega:** fluxo de colaboração versionado
- **Laboratório:** [`../exemplos/aula-3.5/index.html`](../exemplos/aula-3.5/index.html)

## Introdução

### O que é Git?

Git é um sistema de controle de versão distribuído. Ele registra versões dos
arquivos, permite comparar mudanças, criar linhas paralelas de trabalho e recuperar
estados anteriores.

Git não é uma linguagem de programação e não é um serviço de armazenamento em
nuvem. É um programa que pode ser instalado e executado no computador.

### Todo Git é GitHub?

Não. **Git** é a tecnologia de versionamento. **GitHub** é uma plataforma que
hospeda repositórios Git e acrescenta recursos como pull requests, issues, revisão,
permissões e automações.

Outras plataformas incluem GitLab, Bitbucket e servidores próprios. Também é
possível usar Git sem nenhuma delas.

| Termo | O que é |
|---|---|
| Git | Programa de controle de versão |
| GitHub | Serviço que hospeda repositórios Git |
| Repositório | Histórico e arquivos de um projeto |
| Remoto | Outra cópia do repositório acessível por endereço |
| Pull request | Proposta de integração oferecida pela plataforma |

### Consigo ter Git local?

Sim. Este fluxo funciona sem internet:

```bash
git init
git add .
git commit -m "Cria estrutura inicial"
```

Os commits ficam na pasta oculta `.git` do próprio projeto. Um remoto só é
necessário para compartilhar, manter outra cópia ou colaborar pela rede.

### Git é um backup?

Ele ajuda a recuperar versões, mas um repositório somente no mesmo disco não é um
backup suficiente. Se o disco falhar, arquivos e histórico podem ser perdidos.
Mantenha cópias remotas e uma estratégia de backup adequada.

### O que é uma branch?

Branch é um nome móvel que aponta para uma sequência de commits. Ela permite
desenvolver uma mudança sem alterar imediatamente a linha principal.

```bash
git switch -c feature/filtro-tarefas
```

Criar uma branch é uma operação local. Publicá-la é outra ação:

```bash
git push -u origin feature/filtro-tarefas
```

### O que é pull request?

Pull request, ou PR, é uma proposta feita em uma plataforma como GitHub para
integrar uma branch em outra. Ele oferece conversa, revisão e verificações.

Não existe um comando Git universal chamado `git pull-request`. O PR pertence à
plataforma. No GitLab, o recurso equivalente é chamado merge requisição.

### `git pull` é a mesma coisa que pull request?

Não:

- `git pull`: comando Git que busca e integra mudanças de um remoto;
- pull request: página de revisão e proposta de integração em uma plataforma.

### Onde isso entra no projeto?

Criaremos uma branch para uma funcionalidade do painel TypeScript, produziremos
commits pequenos, executaremos a porta de qualidade da aula anterior e simularemos
uma revisão antes da integração.

## Objetivos

Ao final da aula, o aluno deverá conseguir:

1. diferenciar Git e GitHub;
2. criar e usar um repositório local;
3. explicar working tree, staging area e commit;
4. inspecionar mudanças antes de registrá-las;
5. criar branches;
6. realizar commits claros e pequenos;
7. diferenciar repositório local e remoto;
8. usar `fetch`, `pull` e `push` conscientemente;
9. explicar pull requests;
10. identificar e resolver conflitos simples;
11. executar uma revisão antes do merge;
12. evitar o versionamento de segredos.

## Pré-requisitos

- terminal e sistema de arquivos;
- Aula 3.4 concluída;
- projeto TypeScript com comandos de qualidade.

## Pergunta orientadora

> Como registrar, compartilhar e revisar mudanças sem perder a história nem misturar trabalhos incompletos?

## Roteiro sugerido

| Etapa | Duração |
|---|---:|
| Git local e modelo mental | 30 min |
| Commits e branches | 30 min |
| Remotos e sincronização | 20 min |
| Pull request, revisão e merge | 20 min |
| Laboratório | 15 min |
| Revisão | 5 min |

## 1. Instalação e identificação

Verifique:

```bash
git --version
```

Configure a autoria dos commits:

```bash
git config --global user.name "Seu Nome"
git config --global user.email "voce@exemplo.com"
```

Esses dados identificam autoria; não autenticam automaticamente no GitHub.

## 2. Configuração global e local

Configuração global vale para o usuário. Configuração local, armazenada em
`.git/config`, vale somente para o repositório e pode sobrescrever a global:

```bash
git config user.email "email-do-projeto@exemplo.com"
```

Para descobrir a origem de cada valor:

```bash
git config --list --show-origin
```

## 3. Criando um repositório local

Dentro da pasta do projeto:

```bash
git init
```

Isso cria `.git`, onde ficam objetos, referências e configurações. Não execute
`git init` em pastas amplas com arquivos pessoais.

## 4. Clonar ou inicializar?

- `git init`: começa um histórico em uma pasta;
- `git clone URL`: cria uma cópia local de um repositório existente e normalmente
  configura um remoto.

Clonar não significa editar diretamente o servidor. O trabalho continua local até
um `push`.

## 5. Os três espaços principais

```text
Working tree → Staging area → Repositório local
    git add          git commit
```

- **working tree:** arquivos que você edita;
- **staging area:** seleção preparada para o próximo commit;
- **repositório local:** histórico confirmado dentro de `.git`.

O remoto é uma quarta localização, sincronizada separadamente.

## 6. `git status`

```bash
git status
```

Ele mostra branch atual, arquivos modificados, preparados e não rastreados. Use
antes e depois de operações importantes.

## 7. Arquivos rastreados e não rastreados

Um arquivo novo começa como untracked. Depois de ser incluído em um commit, passa a
ser rastreado. Modificações posteriores aparecem no status.

Git não acompanha pastas vazias; acompanha conteúdo de arquivos.

## 8. Inspecionando diferenças

Mudanças ainda não preparadas:

```bash
git diff
```

Mudanças no staging:

```bash
git diff --staged
```

Revise o diff para evitar arquivos acidentais, registros, credenciais ou código de
depuração.

## 9. Staging area

Prepare um arquivo específico:

```bash
git add src/task-service.ts
```

Preparar tudo com `git add .` é conveniente, mas exige revisão. A staging area
permite formar um commit coerente mesmo quando a pasta contém outras alterações.

## 10. Retirando do staging

```bash
git restore --staged src/task-service.ts
```

Isso remove o arquivo da seleção do próximo commit sem apagar a alteração da
working tree.

## 11. Commit

```bash
git commit -m "Adiciona filtro de tarefas por status"
```

Um commit é um registro do estado preparado, com autor, data, mensagem e ligação ao
commit anterior. Ele não envia nada à internet.

## 12. Mensagens úteis

Prefira mensagens que descrevam intenção:

```text
Adiciona validação do status da tarefa
Corrige total exibido no resumo
Documenta execução dos testes
```

Evite `alterações`, `teste`, `coisas` ou uma sequência de `final-agora-vai`.

## 13. Commits pequenos e coerentes

Um bom commit:

- possui uma finalidade;
- mantém o projeto em estado compreensível;
- não mistura refatoração e funcionalidade sem necessidade;
- pode ser revisado e revertido com menor risco.

Pequeno não significa uma linha; significa uma unidade lógica.

## 14. Histórico

```bash
git log --oneline --decorate --graph --all
```

O histórico ajuda a entender quando branches divergiram e onde referências apontam.

## 15. O que é `HEAD`?

`HEAD` representa a posição atualmente selecionada, normalmente a branch ativa. Ao
fazer commit, a branch e `HEAD` avançam para o novo commit.

Evite manipular `.git` manualmente; use comandos Git.

## 16. Criando uma branch

```bash
git switch -c feature/filtro-tarefas
```

O comando cria a branch a partir do commit atual e muda para ela. Nomes como
`feature/...`, `fix/...` e `docs/...` comunicam propósito, mas a convenção deve ser
definida pela equipe.

## 17. Alternando branches

```bash
git switch main
git switch feature/filtro-tarefas
```

Mudanças não confirmadas podem impedir ou acompanhar a troca. Consulte `git status`
antes de mudar.

## 18. Branch não é uma cópia completa

Git armazena objetos e referências de maneira eficiente. Uma branch é, em essência,
um apontador para um commit. Por isso criar branches costuma ser rápido.

## 19. `.gitignore`

Exemplo:

```text
node_modules/
dist/
coverage/
.env
```

`.gitignore` não remove um arquivo que já foi rastreado. Além disso, ignorar `.env`
não apaga um segredo que já entrou no histórico.

## 20. Segredos nunca devem ser commitados

Não versione:

- senhas;
- tokens;
- chaves privadas;
- credenciais do banco;
- arquivos reais de ambiente.

Use `.env.example` somente com nomes de variáveis e valores fictícios. Se um segredo
for exposto, revogue-o; apagar o arquivo do último commit não basta.

## 21. Repositório remoto

Um remoto é um nome associado a uma URL:

```bash
git remote add origin https://servidor/equipe/projeto.git
git remote -v
```

`origin` é uma convenção, não uma palavra obrigatória. O remoto pode estar no GitHub,
GitLab, rede interna ou até em outro caminho acessível.

## 22. Branch local e branch remota

`main` e `origin/main` não são o mesmo objeto:

- `main`: branch local que você move com commits;
- `origin/main`: referência local da última posição conhecida no remoto.

`git fetch` atualiza referências remotas sem integrar automaticamente na branch
atual.

## 23. `fetch`, `pull` e `push`

```bash
git fetch origin
git pull --ff-only
git push
```

- `fetch`: baixa referências e objetos;
- `pull`: busca e integra na branch atual;
- `push`: envia referências e objetos locais ao remoto.

Prefira entender o que será integrado em vez de usar `pull` mecanicamente.

## 24. Publicando uma branch

```bash
git push -u origin feature/filtro-tarefas
```

`-u` configura a relação de acompanhamento. Depois, `git push` e `git pull` sabem
qual branch remota usar, conforme configuração.

## 25. Autenticação

Um remoto HTTPS pode usar credencial gerenciada ou token. Um remoto SSH usa chaves.
Isso autentica o acesso à plataforma; é diferente de `user.name` e `user.email` dos
commits.

Nunca coloque token dentro da URL versionada ou de scripts do projeto.

## 26. Pull request

Após publicar a branch, a plataforma permite abrir uma proposta:

```text
feature/filtro-tarefas → main
```

Um bom PR informa:

- problema e solução;
- alterações principais;
- como testar;
- evidências relevantes;
- riscos e pontos de atenção.

## 27. Revisão de código

O revisor verifica correção, clareza, segurança, testes e aderência ao escopo. A
revisão deve discutir o código, não a pessoa.

Comentários úteis explicam impacto e sugerem uma ação verificável.

## 28. Verificações automáticas

O PR pode executar:

```bash
npm ci
npm run quality
```

Um fluxo aprovado é evidência importante, mas não substitui a revisão humana nem
garante ausência de todos os defeitos.

## 29. Merge

Estratégias comuns:

- merge commit: preserva explicitamente a integração;
- squash: reúne os commits do PR em um commit;
- rebase merge: reaplica commits em uma linha linear.

A equipe deve escolher uma política consistente. Não existe uma estratégia melhor
para todos os contextos.

## 30. Conflitos

Um conflito ocorre quando Git não consegue decidir sozinho como combinar mudanças.
O arquivo pode conter marcadores:

```text
<<<<<<< HEAD
versão atual
=======
outra versão
>>>>>>> feature
```

Leia as duas intenções, edite o resultado correto, remova os marcadores, execute os
testes e então prepare a resolução.

## 31. Conflito não é erro da pessoa

Conflitos são consequência normal de trabalhos que tocaram regiões relacionadas.
Resolva com contexto de negócio; escolher sempre “ours” ou “theirs” pode descartar
uma mudança necessária.

## 32. Atualizando a branch

Antes do merge, a equipe pode integrar `main` na feature por merge ou rebase. Rebase
reescreve commits; evite reescrever histórico compartilhado sem coordenação.

Nunca use `push --force` de forma automática. Se a política exigir atualização de
uma branch própria, entenda o impacto e prefira proteções como `--force-with-lease`.

## 33. Desfazendo com segurança

Para desfazer um commit já compartilhado:

```bash
git revert IDENTIFICADOR
```

Isso cria um novo commit inverso e preserva o histórico. Comandos que reescrevem ou
apagam trabalho exigem mais cuidado.

## 34. Laboratório guiado

Abra o [simulador de fluxo Git](../exemplos/aula-3.5/index.html).

### Etapa 1 — Trabalhe localmente

Edite o arquivo, prepare a mudança e crie um commit. Observe que nenhuma dessas
ações exige GitHub ou internet.

### Etapa 2 — Crie uma branch

Abra a branch de funcionalidade antes de editar. Veja os apontadores locais
mudarem.

### Etapa 3 — Configure o remoto

Conecte um remoto simulado e publique a branch. Só aqui a mudança sai do repositório
local.

### Etapa 4 — Abra e revise o PR

O pull request só fica disponível depois que a branch existe no remoto. Execute a
qualidade e aprove a revisão antes do merge.

## 35. Fluxo recomendado da aula

```text
atualizar main
→ criar branch
→ editar
→ revisar diff
→ preparar
→ executar qualidade
→ commit
→ publicar branch
→ abrir PR
→ revisar
→ integrar
```

## 36. Erros comuns

### Achar que commit envia ao GitHub

Commit é local. `push` sincroniza com o remoto.

### Trabalhar sempre na `main`

Isso mistura trabalho incompleto com a linha de integração.

### Versionar `node_modules`

O projeto deve registrar manifesto e lockfile, não a pasta instalada.

### Commitar segredos

Mesmo removidos depois, eles podem permanecer no histórico.

### Fazer um commit com assuntos diferentes

Revisão e reversão ficam mais difíceis.

### Resolver conflito sem testar

Um arquivo sem marcadores ainda pode estar logicamente incorreto.

## 37. Boas práticas

- execute `git status` frequentemente;
- examine `git diff` antes de preparar;
- examine `git diff --staged` antes de confirmar;
- crie branches com propósito claro;
- produza commits coerentes;
- não versione segredos ou dependências instaladas;
- sincronize conscientemente;
- descreva como testar o PR;
- mantenha verificações aprovadas;
- trate revisão como colaboração técnica.

## 38. Exercícios

### Exercício 1 — Conceitos

Classifique operações como local, remota ou pertencente à plataforma.

### Exercício 2 — Primeiro histórico

Crie um repositório local com três commits pequenos e inspecione o registro.

### Exercício 3 — Staging seletivo

Altere dois arquivos e inclua apenas um no próximo commit.

### Exercício 4 — Branch

Crie `feature/resumo-tarefas`, confirme uma mudança e retorne à `main`.

### Exercício 5 — Revisão

Escreva título, descrição e roteiro de testes para um PR simulado.

## 39. Desafio

Entregue um fluxo completo que contenha:

- repositório local;
- `.gitignore` seguro;
- branch de funcionalidade;
- pelo menos dois commits coerentes;
- fluxo de qualidade aprovado;
- branch publicada;
- descrição de pull request;
- revisão simulada;
- registro da estratégia de merge escolhida.

## 40. Lista de verificação de conclusão

- [ ] Sei diferenciar Git e GitHub.
- [ ] Consigo usar Git somente local.
- [ ] Entendo working tree, staging e commit.
- [ ] Reviso diff antes do commit.
- [ ] Crio e alterno branches.
- [ ] Diferencio branch local e remota.
- [ ] Diferencio fetch, pull e push.
- [ ] Sei explicar pull request.
- [ ] Entendo como resolver um conflito simples.
- [ ] Nunca versiono segredos.

## 41. Critérios de avaliação

| Critério | Pontos |
|---|---:|
| Modelo mental do Git | 20 |
| Commits coerentes | 20 |
| Uso de branches | 15 |
| Sincronização remota | 15 |
| Pull request e revisão | 20 |
| Segurança do repositório | 10 |
| **Total** | **100** |

## Resumo

Nesta aula, aprendemos que:

- Git é independente de GitHub;
- repositórios e commits podem ser totalmente locais;
- staging seleciona o próximo commit;
- branches são apontadores para commits;
- remotos são cópias sincronizadas separadamente;
- `git pull` não é pull request;
- pull request pertence à plataforma de colaboração;
- revisão, qualidade e merge completam o fluxo;
- segredos não devem entrar no histórico.

## Próxima aula

Na Aula 3.6, reuniremos testes, documentação e todo o projeto TypeScript em uma
entrega final reproduzível.
