Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
Erro resolvidoIniciantecódigo testado

fatal: refusing to merge unrelated histories — resolver

Por que o Git recusa unir dois históricos sem commit em comum, como reproduzir o erro em 40 segundos e as duas saídas: allow-unrelated-histories ou clone.

Rodolfo Mori4 min de leitura

fatal: refusing to merge unrelated histories aparece quando as duas pontas não compartilham nenhum commit ancestral e você pede um merge comum. Isso acontece quando o projeto local ganhou um commit inicial e o remoto foi criado separadamente com README, licença ou .gitignore.

O erro foi reproduzido com dois repositórios locais independentes e um bare, sem tocar no GitHub:

bash
git --version
git version 2.54.0 (Apple Git-156)

A mensagem curta esconde duas raízes

O projeto local continha feat: cria app local; o remote continha Initial commit. O pull especificou merge para não parar antes na configuração de estratégia do Git atual:

bash
git pull --no-rebase origin main
From /tmp/grupo-git-unrelated-erro.UHzST0/central * branch main -> FETCH_HEAD * [new branch] main -> origin/main fatal: refusing to merge unrelated histories

Sem --no-rebase, Git 2.54 também pode pedir que você defina como reconciliar branches divergentes antes de chegar à verificação de ancestral. São mensagens diferentes em etapas diferentes. Para diagnosticar este artigo, escolha merge explicitamente e observe a recusa por histórico.

Unrelated quer dizer sem ancestral comum

Cada git init seguido de primeiro commit cria uma raiz. O comando abaixo mostrou duas raízes completas antes da união:

bash
git rev-list --max-parents=0 HEAD origin/main
06ee608823898f2e7723ea40d614c3ca6b8317c1 8ab05438e8b6e5f0229e551a28049dc98d472b23

Pense em duas árvores genealógicas sem pessoa em comum. O merge normal espera um ancestral que permita calcular base e diferenças. O limite da analogia é que o Git ainda consegue criar uma união especial quando você confirma que as duas árvores pertencem ao mesmo projeto.

Reproduza com local e remoto inicializados separados

O cenário mínimo cria um bare, envia para ele o README de um repositório semente e, em outra pasta, cria um projeto com seu próprio primeiro commit. Só depois o projeto local recebe origin. Os caminhos temporários variam; o comportamento importante é que cada working tree ganhou uma raiz antes da conexão. Use nomes e e-mails de teste, e nunca coloque credenciais reais no sandbox.

Permita a união somente quando ela é intencional

Se os dois lados contêm trabalho que precisa ser preservado, confirme a exceção:

bash
git pull origin main --allow-unrelated-histories --no-rebase
From /tmp/grupo-git-unrelated.tL788v/central * branch main -> FETCH_HEAD Auto-merging README.md CONFLICT (add/add): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.

A opção não escolhe conteúdo. Ela apenas remove a proteção contra duas raízes. Como ambos criaram README.md, surgiu um conflito add/add.

bash
sed -n '1,20p' README.md
<<<<<<< HEAD # Livraria criada localmente ======= # Livraria criada no remoto >>>>>>> 8ab05438e8b6e5f0229e551a28049dc98d472b23

Resolva com um README que represente o projeto unido, teste instruções e faça commit. Não apague um lado apenas porque ele aparece abaixo do separador.

O grafo final continua mostrando duas origens

Depois da resolução, o merge real ficou:

bash
git --no-pager log --oneline --graph --all -5
* 5b42c81 merge: une históricos local e remoto |\ | * 8ab0543 Initial commit * 06ee608 feat: cria projeto local

E as raízes permaneceram consultáveis:

bash
git rev-list --max-parents=0 HEAD
06ee608823898f2e7723ea40d614c3ca6b8317c1 8ab05438e8b6e5f0229e551a28049dc98d472b23

Isso não é corrupção. É um histórico válido com duas raízes reunidas por um commit de merge.

Escolha entre unir e recomeçar pela história que precisa ficar

Use --allow-unrelated-histories quando os dois lados contêm commits que explicam decisões reais e devem continuar auditáveis. Resolva cada conflito, rode testes e descreva no commit por que duas origens foram reunidas. O merge especial fica visível para sempre e isso é uma vantagem quando corresponde ao que aconteceu.

Prefira clonar e mover arquivos quando um dos lados contém apenas inicialização automática ou poucos commits descartáveis. Você reduz a complexidade para uma raiz e evita ensinar ao time que toda divergência deve ser forçada. Preserve a pasta antiga até comparar quantidade de arquivos, configuração e resultado da aplicação.

Não use a quantidade de commits como único critério. Um único commit pode conter uma decisão de licença que precisa ser mantida, enquanto dez commits locais de experimento podem não ter valor histórico. Leia mensagens, diffs e autoria. Se o repositório já é compartilhado, converse antes: recomeçar por force muda a referência que outras cópias usam.

Em ambos os caminhos, o objetivo é alinhar a narrativa técnica com a origem real. O Git aceita duas raízes quando você autoriza; ele não decide se essa forma representa melhor o projeto.

A correção mais limpa pode ser clonar e mover arquivos

Se o remote contém apenas o README inicial e o local ainda não foi publicado, clonar o remote numa pasta nova e mover os arquivos de trabalho para dentro produz uma história de uma raiz. Revise o diff, commit e preserve a pasta antiga até conferir que nada faltou.

bash
git clone /tmp/grupo-git-unrelated.tL788v/central.git projeto-limpo
Cloning into 'projeto-limpo'... done.

Não copie .git da pasta antiga. Copie os arquivos do projeto, respeite o .gitignore e crie um commit sobre a raiz remota. Essa opção é mais simples quando o histórico local tem pouco valor; a união é melhor quando ambos os lados possuem decisões que precisam continuar auditáveis.

Não use --force para apagar o remote sem confirmar. O erro está protegendo uma história independente. A prevenção está em criar o GitHub vazio quando o local já existe, como explica remote e push. Para resolver os marcadores, use o método de merge; se a mensagem for rejeição de push, consulte remote contains work.

Sua missão é reproduzir duas raízes em pastas temporárias, provar com rev-list, unir e desenhar o grafo. Depois repita pela estratégia de clone e compare qual histórico conta melhor a origem real do projeto.

  • git
  • erro
  • merge
  • unrelated histories
  • github

Perguntas frequentes

--allow-unrelated-histories apaga um dos históricos?
Não. Ele permite que o merge crie uma união com duas raízes. Pode haver conflitos, especialmente se os dois lados criaram o mesmo arquivo.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em git version 2.54.0 (Apple Git-156) no macOS 27, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Git — git merge — git-scm.com
  2. GitHub Docs — Adicionar código hospedado localmente — docs.github.com

Continue por aqui