Diferença entre merge e rebase no Git

Nenhum rebase nem merge, sozinhos, “apagam” seus trabalhos — em ambos os casos, seus commits permanecem no repositório (na história da branch ou como SHAs antigos, enquanto o reflog estiver ativo).

  • pull.rebase false (merge): O git pull criará um commit de merge, seus e os commits do remoto não serão reescritos, a história da branch simplesmente se unirá à branch remota. Visualmente, é “mais seguro” para a cabeça: você vê claramente as linhas se encontrando.
  • pull.rebase true (rebase): Seus commits locais serão copiados sobre os remotos (novos hashes). O conteúdo dos commits geralmente é o mesmo, mas os “antigos” commits podem permanecer apenas no git reflog após um rebase bem-sucedido — isso é normal, e, se algo der errado, você pode restaurar (git reset --hard para o ref desejado no reflog).

Se o objetivo principal é “não perder trabalhos”:

  1. Antes de passos arriscados — faça um commit (ou git stash) e, opcionalmente, uma branch separada (git branch backup-tgisn-46) — uma cópia do ponteiro, backup barato.
  2. Não confunda com perdas causadas por comandos como git reset --hard, force push sem necessidade, git clean -fd.
  3. Após rebase/merge, evite executar git gc agressivamente nos próximos dias — o reflog mantém um ponto de retorno.

Prático para “não perder, não complicar muito a história”: git config pull.rebase false — em caso de divergência, você sempre receberá um merge, sem reescrever seus commits locais. Se você já está confortável com o rebase (como no antigo pull --rebase) — pode deixar pull.rebase true, mas não faça push --force em branches compartilhadas sem acordo prévio.

Conclusão: não há perda de trabalhos devido à escolha da estratégia pull; o risco está em outras comandos e em force push; para tranquilidade — faça um commit + branch de backup antes de operações confusas.

Aqui está a mesma situação que você teve: um único commit comum C, depois, no origin, cinco commits r1…r5, na local — um único L (meu trabalho).

1. Antes do pull (divergência)

gitGraph
  commit id: "C (comum)"
  branch local
  checkout local
  commit id: "L (meu commit)"
  checkout main
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"

Significado: ponta da local = L, ponta da main = r5, ancestral comum = C. Isso não foi perdido em ambos os casos — apenas como a história é “costurada” muda.


2. Após git pull sem rebase (pull.rebase falsemerge)

gitGraph
  commit id: "C"
  branch local
  checkout local
  commit id: "L"
  checkout main
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"
  checkout local
  merge main
  commit id: "M (commit de merge)"

Aparece um commit de merge M com dois pais (L e r5). Os commits L e r1…r5 como objetos permanecem; a história é ramificada, sem reescrita.


3. Após git pull com rebase (pull.rebase truerebase)

gitGraph
  commit id: "C"
  commit id: "r1"
  commit id: "r2"
  commit id: "r3"
  commit id: "r4"
  commit id: "r5"
  commit id: "L′ (mesmo patch, novo hash)"

A história é linear: seu trabalho está em cima dos remotos. O commit L na história tem um novo commit L′ (mesmo diff em relação a r5, hash diferente); o antigo L ainda é visível no git reflog por algum tempo, até que você exclua o reflog expire.


Resumo: merge — ramificação + nó de merge; rebase — uma linha, seu commit “regravado” sobre os remotos. Seu trabalho, no sentido de mudanças nos arquivos, não desaparece em ambos os cenários normais; o que muda é a forma da história e o hash do commit local no rebase.