Merging & Rebasing
Duas estratégias para combinar branches - merge preserva o histórico como está, rebase reescreve-o para uma linha do tempo linear.
Busque em todas as páginas da documentação
Duas estratégias para combinar branches - merge preserva o histórico como está, rebase reescreve-o para uma linha do tempo linear.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Cartão de referência rápida - pronto para copiar e colar.
# Fazer merge de um branch de funcionalidade em main
git checkout main
git merge feature/auth-page
# Rebase de um branch de funcionalidade sobre o main mais recente
git checkout feature/auth-page
git rebase main
# Rebase interativo - achatar (squash), reordenar, editar commits
git rebase -i main
# Abortar um merge ou rebase com conflito
git merge --abort
git rebase --abortQuando usar isso: Sempre que precisar integrar alterações de um branch em outro.
# Atualizar main
git checkout main
git pull origin main
# Fazer merge do branch de funcionalidade
git merge feature/user-profile
# Se ocorrerem conflitos, resolva-os:
# 1. Abra os arquivos em conflito (marcados com <<<<<<< / ======= / >>>>>>>)
# 2. Edite para manter o código correto
# 3. Adicione os arquivos resolvidos ao stage
git add src/components/UserProfile.tsx
# 4. Conclua o merge
git commitO que isso demonstra:
main mais recente antes de fazer merge<<<<<<<, =======, >>>>>>># Comece no seu branch de funcionalidade
git checkout feature/dashboard
# Fazer rebase sobre o main mais recente
git fetch origin
git rebase origin/main
# Se ocorrerem conflitos durante o rebase:
# 1. Resolva o conflito no arquivo
# 2. Adicione o arquivo resolvido ao stage
git add src/app/dashboard/page.tsx
# 3. Continue o rebase
git rebase --continue
# Force push após o rebase (necessário pois o histórico mudou)
git push --force-with-leaseO que isso demonstra:
git fetch + git rebase origin/main evita a necessidade de fazer checkout de main primeiro--force-with-lease é mais seguro que --force - ele se recusa a fazer push se o remoto tiver commits que você ainda não viu| Merge | Rebase | |
|---|---|---|
| Histórico | Preserva todos os commits e cria um commit de merge | Reescreve commits para um histórico linear |
| Conflitos | Resolva uma vez no commit de merge | Resolva por commit durante a reaplicação |
| Branches compartilhados | Seguro - nunca reescreve histórico publicado | Perigoso em branches compartilhados - reescreve commits nos quais outros podem ter baseado trabalho |
| Melhor para | Integrações do branch main, branches de release | Manter branches de funcionalidade atualizados, limpeza antes do PR |
Regra geral: Faça rebase em seus próprios branches de funcionalidade. Faça merge em branches compartilhados.
O rebase interativo permite que você limpe commits antes de fazer o merge de um PR.
# Fazer rebase dos últimos 4 commits
git rebase -i HEAD~4Isso abre um editor com seus commits:
pick abc1234 feat: add dashboard layout
pick def5678 fix: typo in dashboard
pick ghi9012 feat: add chart component
pick jkl3456 fix: chart responsive issue
Operações comuns:
# Achatar (Squash) um fix no commit anterior
pick abc1234 feat: add dashboard layout
squash def5678 fix: typo in dashboard
pick ghi9012 feat: add chart component
squash jkl3456 fix: chart responsive issue
# Renomear a mensagem de um commit
reword abc1234 feat: add dashboard layout
# Reordenar commits (apenas mova as linhas)
pick ghi9012 feat: add chart component
pick abc1234 feat: add dashboard layout
# Remover um commit completamente
drop def5678 fix: typo in dashboard
Quando o Git não consegue fazer o merge automático, ele marca o arquivo:
<<<<<<< HEAD
export function Header({ title }: { title: string }) {
return <h1 className="text-2xl font-bold">{title}</h1>;
=======
export function Header({ title, subtitle }: HeaderProps) {
return (
<header>
<h1 className="text-3xl font-bold">{title}</h1>
<p className="text-muted-foreground">{subtitle}</p>
</header>
);
>>>>>>> feature/header-redesign
}Passos para resolver:
<<<<<<<, =======, >>>>>>>)# Merge fast-forward (sem commit de merge, histórico linear)
git merge --ff-only feature/small-fix
# Forçar um commit de merge mesmo quando fast-forward é possível
git merge --no-ff feature/auth-pageCoisas que vão te morder. Cada armadilha inclui o que dá errado, por que acontece e a correção.
Rebasar um branch compartilhado - Se outros basearam trabalho em seu branch e você fizer force-push de um rebase, o histórico deles divergirá. Correção: Rebase apenas branches que são exclusivamente seus. Use merge para branches compartilhados.
Force push destruindo trabalho - git push --force sobrescreve o remoto incondicionalmente. Correção: Sempre use git push --force-with-lease, que se recusa a fazer push se outra pessoa fez push desde o seu último fetch.
Fadiga de conflitos durante o rebase - Um rebase em muitos commits pode apresentar o mesmo conflito repetidamente. Correção: Use git rerere (reutilizar resolução gravada) para resolver automaticamente conflitos repetidos: git config rerere.enabled true.
Commits perdidos após rebase - Commits parecem desaparecer após um rebase mal sucedido. Correção: git reflog mostra todas as posições recentes do HEAD. Encontre o hash do commit e git checkout -b recovery <hash>.
Ruído de commits de merge - Commits de merge frequentes ao puxar main para o seu branch de funcionalidade poluem o histórico. Correção: Use git pull --rebase em vez disso, ou configure-o globalmente: git config pull.rebase true.
Outras maneiras de resolver o mesmo problema - e quando cada uma é a melhor escolha.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
git cherry-pick | Você precisa de um commit específico de outro branch | Você precisa de todas as alterações de um branch |
Squash merge (gh pr merge --squash) | O branch de funcionalidade tem muitos commits de WIP ou de correção | Você deseja preservar o histórico de commits individuais |
git merge --squash | Combinar todas as alterações em um único commit localmente | O branch tem commits atômicos significativos que valem a pena manter |
mainmain ou develop--force-with-lease se recusa a fazer push se o branch remoto tiver commits que você ainda não baixou (fetched)--force sobrescreve o remoto incondicionalmente, potencialmente destruindo o trabalho de colegas de equipe--force-with-lease após um rebasegit rebase -i HEAD~4
# Mude "pick" para "squash" (ou "s") nos commits que você deseja incorporar
# Salve e feche o editor, depois edite a mensagem do commit combinado<<<<<<< HEAD marca o início da versão do seu branch atual======= separa as duas versões conflitantes>>>>>>> branch-name marca o fim da versão do branch de entradagit rerere para resolver automaticamente conflitos repetidos:git config --global rerere.enabled true--ff-only move o ponteiro do branch para frente sem um commit de merge (histórico linear)--no-ff sempre cria um commit de merge, preservando o fato de que um branch de funcionalidade existiu--ff-only falha se os branches divergiramgit reflog
# Encontre o hash do commit antes do início do rebase
git checkout -b recovery <hash>git fetch origin e depois git reset --hard origin/branch-name (se ele não tiver commits locais)git merge --abort
# ou
git rebase --abortmain, facilitando o git bisectgit pull = git fetch + git merge (cria um commit de merge se os branches divergiram)git pull --rebase = git fetch + git rebase (reaplica seus commits locais sobre os remotos)--rebase para evitar commits de merge ruidosos ao atualizar um branch de funcionalidade.ts em conflito e combine ambas as definições de tipo se forem compatíveisnpx tsc --noEmit após resolver para verificar se os tipos mesclados compilamRevisado por Chris St. John·Última atualização: 10 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥