Trabalhou numa branch feature, o código está pronto. É preciso agora reintegrá-lo em main. O Git oferece dois mecanismos para isso: a fusão (merge) e o rebasamento (rebase).
Os dois atingem o mesmo objetivo — reunir o trabalho — mas com uma forma de histórico diferente. É todo o desafio desta lição.
| Mecanismo | Ideia numa frase |
|---|---|
| Merge | Cria-se um commit que junta as duas branches, mantendo a história tal qual. |
| Rebase | Reproduzem-se os commits de uma branch por cima de outra, como se se tivesse começado mais tarde. |
Antes de qualquer integração, confirma-se que se tem a última versão:
git switch main
git pull origin mainO comando git merge reúne uma branch noutra. Existem dois casos.
Caso 1 — Fusão rápida (fast-forward): se main não se moveu desde a criação da branch, o Git avança simplesmente o ponteiro. Nenhum commit de fusão é criado.
Caso 2 — Fusão a três branches (three-way merge): se main recebeu novos commits entretanto, o Git cria um commit de fusão que tem dois pais.
# Colocar-se na branch alvo e depois fundir
git switch main
git merge feature/panier
# Forçar um commit de fusão mesmo que o fast-forward seja possível
git merge --no-ff feature/panier| Opção | Efeito |
|---|---|
git merge feature | Fusão (fast-forward se possível) |
git merge --no-ff feature | Criar sempre um commit de fusão (fica o rasto da branch) |
git merge --abort | Anular uma fusão em conflito |
O merge preserva a história real: vê-se quando e como as branches se juntaram. É honesto, mas o histórico pode tornar-se denso com muitos commits de fusão.
🔧 Mini-exercício — Quer fundir feature/panier em main forçando a criação de um commit de fusão, mesmo que um fast-forward fosse possível. Escreva o comando.
git merge --no-ff feature/panier — o --no-ff guarda um rasto explícito da branch fundida.
O git rebase desloca os commits da sua branch para os reproduzir por cima da ponta de outra branch. Resultado: um histórico linear, como se tivesse começado o trabalho depois dos últimos commits de main.
Antes do rebase:
Depois de git rebase main (os commits B e C são reproduzidos após D):
# Na branch feature, reproduzir por cima de main
git switch feature/panier
git rebase main
# Depois fusão fast-forward limpa em main
git switch main
git merge feature/panier| Vantagem do rebase | Precaução |
|---|---|
| Histórico linear e legível | Reescreve os commits (novos SHA) |
| Sem commits de fusão parasitas | Nunca rebasar uma branch já enviada e partilhada |
| Ideal antes de uma pull request | Conflitos a resolver commit a commit |
⚠️ Regra de ouro do rebase: nunca rebase commits já publicados e usados por outros. Está a reescrever a história, o que partiria os repositórios deles. O rebase é para o trabalho local não partilhado.
🔧 Mini-exercício — Está na branch feature/panier. Escreva o comando para reproduzir os seus commits por cima da ponta de main (histórico linear).
git rebase main (estando de facto em feature/panier).
Um conflito ocorre quando o Git não consegue decidir automaticamente: duas branches modificaram a mesma linha do mesmo ficheiro. O Git pára e pede-lhe que decida.
O Git insere marcadores de conflito no ficheiro:
<<<<<<< HEAD
prix = 10 # versão de main
=======
prix = 12 # versão de feature
>>>>>>> feature/panierA resolução passo a passo:
<<<<<<<, =======, >>>>>>>.git add.# Ver os ficheiros em conflito
git status
# Depois da edição manual
git add fichier-en-conflit.py
# Terminar um merge
git commit
# Terminar um rebase
git rebase --continue
# Em caso de pânico: anular tudo
git merge --abort # ou: git rebase --abort| Ferramenta de ajuda | Uso |
|---|---|
git status | Listar os ficheiros em conflito |
git diff | Ver as diferenças conflituosas |
git mergetool | Lançar uma ferramenta gráfica de resolução |
| VS Code | Botões Accept Current / Incoming / Both |
Um conflito não é um erro: é o Git a dizer-lhe, com honestidade, « não sei qual ficar, a decisão é sua ». Manter a calma e ler os marcadores chega em 99 % dos casos.
🔧 Mini-exercício — Editou o ficheiro app.py para resolver um conflito ocorrido durante um rebase. Que dois comandos terminam a operação?
git add app.py
git rebase --continue(Para um merge, seria git add app.py e depois git commit.)
Os dois reúnem o trabalho, mas produzem um histórico diferente. A escolha é muitas vezes uma convenção de equipa.
| Aspeto | Merge | Rebase |
|---|---|---|
| Histórico | Fiel, ramificado | Linear, limpo |
| Commit de fusão | Sim (se não for fast-forward) | Não |
| Reescreve a história | Não | Sim (novos SHA) |
| Seguro em branch partilhada | ✅ Sim | ❌ Não |
Legibilidade do log | Mais densa | Mais clara |
A prática recomendada mais habitual:
main antes de abrir uma pull request → histórico limpo.main → rasto claro da integração.# 1. Limpar a branch local antes da PR
git switch feature/x
git rebase main
# 2. Depois da PR aprovada, o GitHub faz o mergeFrase mnemónica: « Rebase em privado, merge em público. » Rebasa-se o que é seu, funde-se o que é partilhado.
O que faz git merge feature a partir de main quando main também tem novos commits?
a) Apaga a branch feature
b) Cria um commit de fusão com dois pais
c) Apaga o histórico
d) Recusa sempre fundir
✅ Resposta: b) — É uma fusão a três branches: o Git cria um commit de fusão que reúne as duas histórias.
Qual é o efeito principal de um git rebase main?
a) Reproduzir os commits da branch por cima de main para um histórico linear
b) Clonar o repositório
c) Apagar main
d) Criar uma salvaguarda remota
✅ Resposta: a) — O rebase desloca e reproduz os seus commits no cimo de main, produzindo uma história linear.
Por que não se deve rebasar uma branch já enviada e partilhada?
a) Porque o GitHub o proíbe
b) Porque isso reescreve os commits e parte os repositórios dos outros
c) Porque o rebase é mais lento
d) Porque apaga main
✅ Resposta: b) — O rebase cria novos SHA. Se outros já tiverem esses commits, o histórico deles fica incoerente.
O que representam os marcadores <<<<<<<, =======, >>>>>>>?
a) Comentários de código
b) Um erro de sintaxe Python
c) As zonas de um conflito a resolver à mão
d) O fim de um ficheiro
✅ Resposta: c) — São os marcadores de conflito: acima a versão atual (HEAD), abaixo a versão de entrada. Escolhe-se e apagam-se.
Como anular com limpeza uma fusão bloqueada por conflitos?
a) git delete
b) git merge --abort
c) git reset --cloud
d) Apagar a pasta .git
✅ Resposta: b) — git merge --abort (ou git rebase --abort) devolve o repositório ao estado anterior à operação.
Duas branches modificam a mesma linha de um ficheiro config.txt. Reproduza o conflito e depois resolva-o ficando com as duas informações combinadas.
main, o ficheiro contém port = 8080.feature/ssl muda esta linha para port = 443.main muda a mesma linha para port = 9090.feature/ssl em main, resolva o conflito ficando com port = 443 (HTTPS) e termine.# Preparação: criar o conflito
echo "port = 8080" > config.txt
git add config.txt
git commit -m "Configuração inicial"
git switch -c feature/ssl
echo "port = 443" > config.txt
git commit -am "Passagem a HTTPS (porta 443)"
git switch main
echo "port = 9090" > config.txt
git commit -am "Alteração da porta para 9090"
# Tentativa de fusão → conflito
git merge feature/sslO Git mostra então:
Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.O ficheiro config.txt contém:
<<<<<<< HEAD
port = 9090
=======
port = 443
>>>>>>> feature/sslEdita-se para ficar só com o valor correto:
echo "port = 443" > config.txt # decide-se a favor do HTTPS
git add config.txt
git commit -m "Fusão feature/ssl: conservação da porta 443"Resultado esperado:
| Verificação | Comando | Saída |
|---|---|---|
| Conflito resolvido | git status | « nothing to commit, working tree clean » |
| Conteúdo final | cat config.txt | port = 443 |
| Commit de fusão | git log --oneline -1 | « Fusão feature/ssl: conservação da porta 443 » |
Truque: se se enganar a meio do conflito,
git merge --abortdevolve-lhe o repositório intacto. Não há risco em experimentar.
add, termina-se.main.Já sabe integrar o código tecnicamente. A lição 03 — Pull requests mostra como fazer reler este trabalho antes de o integrar, no centro da colaboração no GitHub.
Todos os direitos reservados. Qualquer reprodução, difusão, utilização ou adaptação deste curso, no todo ou em parte, é estritamente proibida sem a autorização escrita prévia do Dr. Haythem REHOUMA.
Curso criado por Dr. Haythem REHOUMA — Desenvolvimento e implementação de soluções de dados