Artigo original escrito por: Vali Shah
Artigo original: An introduction to Git merge and rebase: what they are, and how to use them
Traduzido e adaptado por: Daniel Rosa

Por sermos desenvolvedores, muitos de nós têm de escolher entre merge e rebase. Com todas as referências que pegamos da internet, todos acreditam em "Não usar o rebase, pois ele pode causar problemas sérios." Aqui, explicarei o que são o merge e o rebase, por que você deve (ou não) utilizá-los, e como fazer isso.

Git merge e git rebase servem ao mesmo propósito. Eles foram projetados para integrar as alterações de diversas branches em uma única. Embora o objetivo final seja o mesmo, esses dois métodos fazem isso de modos diferentes, sendo útil saber a diferença entre eles para auxiliar você a se tornar um desenvolvedor de software melhor.

Essa é uma pergunta que divide a comunidade do Git. Alguns creem que você deve sempre usar o rebase, enquanto outros acham que você deve sempre usar merge. Os dois lados apresentam benefícios convincentes.

Git merge

Fazer um merge é uma prática comum para desenvolvedores que usam sistemas de controle de versão. Sejam as branches criadas para testes ou reparos de bugs, seja por outros motivos, o merge faz o commit de alterações para outro local. Para ser mais específico, o merge leva o conteúdo de uma branch de origem e o integra à branch de destino. Nesse processo, somente a branch de destino é alterada. O histórico da branch de origem permanece o mesmo.

VonhijTBQgjwtRXz31wLzF7iWDnDFk2o8EWi
Merge das branches master e feature (branch de um novo recurso)

Vantagens

  • Simples e conhecido
  • Preserva o histórico completo e a ordem cronológica
  • Mantém o contexto da branch

Desvantagens

  • O histórico de commits pode ficar poluído com os diversos commits das ações de merge
  • Depurar usando git bisect pode ser mais difícil

Como fazer

Fazer o merge da branch master na branch feature usando os comandos checkout e merge.

$ git checkout feature
$ git merge master

(ou)

$ git merge master feature

Isso criará um "commit de merge" na branch feature contendo o histórico das duas branches.

Git rebase

Rebase é a outra maneira de integrar alterações de uma branch em outra. Rebase comprima todas as alterações em um único "patch". Em seguida, ele integra o patch na branch de destino.

Diferente do merge, o rebase "achata" o histórico, pois transfere o trabalho completo de uma branch para outra. No processo, o histórico indesejado é eliminado.

Rebases são a maneira como as alterações devem passar do topo da hierarquia para baixo, enquanto os merges são como eles devem voltar para o topo
aEjZMJ6s4rDVqzXveqgLrwkQ0RJEvOTjAIUc
Rebase da branch feature na master

Vantagens

  • Simplifica um histórico potencialmente complexo
  • Manipular um único commit é fácil (por exemplo, revertê-lo)
  • Evita o "ruído" dos commits de merge em repositórios de muito tráfego com branches de muito tráfego
  • Limpa os commits intermediários, tornando-os um único commit, o que pode ser útil para as equipes de DevOps

Desvantagens

  • Transformar a branch feature em apenas alguns commits pode ocultar o contexto
  • Fazer o rebase de repositórios públicos pode ser perigoso ao trabalhar como uma equipe
  • Dá mais trabalho usar o rebase para manter a branch feature sempre atualizada
  • Fazer o rebase em branches remotas exige o uso de um force push. O maior problema que as pessoas enfrentam é fazerem um force push mas não terem definido um git push padrão. Isso resulta em atualizações a todas as branches que tenham o mesmo nome, seja local ou remotamente, e é um pavor ter de lidar com isso.
Se você fizer o rebase incorretamente e, acidentalmente, reescrever o histórico, isso pode levar a sérios problemas. Por isso, certifique-se de que sabe o que está fazendo!

Como fazer

Fazer o rebase da branch feature na branch master usando os seguintes comandos.

$ git checkout feature
$ git rebase master

Isso move toda a branch feature para a branch master. Isso ocorre ao reescrevermos o histórico do projeto, criando commits totalmente do zero para cada commit na branch (feature) original.

Rebase interativo

Ele permite alterar os commits quando eles são movidos para a nova branch. Ele é mais poderoso que o rebase automatizado, por oferecer controle completo sobre o histórico de commits da branch. Tipicamente, é usado para limpar um histórico bagunçado antes de fazer o merge da branch feature na branch master.

$ git checkout feature
$ git rebase -i master

Isso abrirá o editor, listando todos os commits que estão prestes a ser movidos.

pick 22d6d7c Mensagem do commit nº 1
pick 44e8a9b Mensagem do commit nº 2
pick 79f1d2h Mensagem do commit nº 3

Ele define com exatidão qual será a aparência da branch após a realização do rebase. Ao reordenar as entidades, você pode fazer com que o histórico tenha a aparência que você quiser. Por exemplo, você pode usar comandos como fixup, squash, edit e outros no lugar de pick.

c0OgwrajpcLfLs75zq0mF5DP3sTBQ-oLjU02

Qual deles usar?

Então, qual deles é o melhor? O que recomendam os especialistas?

É difícil generalizar e decidir por um ou por outro, já que cada equipe é diferente. Temos, porém, de começar de algum lugar.

As equipes precisam considerar diversas questões ao definir suas políticas de uso de git rebase e de git merge. Acontece que uma estratégia de fluxo de trabalho não é melhor do que a outra. Tudo depende de sua equipe.

Considere o nível do rebase e a competência do Git dentro de sua organização. Determine o grau de avaliação da simplicidade do rebase em comparação com a rastreabilidade e o histórico do merge.

Por fim, as decisões sobre o merge e o rebase devem ser consideradas no contexto de uma estratégia clara de criação de branches. Uma estratégia de sucesso para a criação de branches é projetada em torno da organização de suas equipes.

O que eu recomendo?

À medida que a equipe cresce, se tornará mais difícil gerenciar o rastrear alterações no desenvolvimento com uma política de sempre usar merge. Para ter um histórico limpo e compreensível dos commits, o uso de rebase é razoável e eficaz.

Considerando as seguintes circunstâncias e diretrizes, você pode obter o melhor do rebase:

  • Você está desenvolvendo no local: se você não tiver compartilhado seu trabalho com mais ninguém. pode preferir o rebase em vez do merge para manter limpo seu histórico. Se você tem um fork pessoal do repositório, que não é compartilhado com outros desenvolvedores, é seguro usar o rebase mesmo após ter feito o push para sua branch.
  • Seu código está pronto para ser revisado: você criou uma pull request. Outras pessoas estão revisando seu trabalho e, potencialmente, fazendo o fetch dele em seus forks para uma revisão local. Neste ponto, você não deve fazer o rebase de seu trabalho. Você deve criar commits de "retrabalho" e atualizar sua branch feature. Isso ajuda na rastreabilidade no pull request e evita a quebra acidental do histórico.
  • A revisão está concluída e pronta para ser integrada à branch de destino. Parabéns! Você está prestes a excluir sua branch feature. Dado que outros desenvolvedores não estarão fazendo o fetch e o merge destas alterações a partir daqui, essa é a sua chance de limpar o histórico. Neste ponto, você pode reescrever o histórico e encolher os commits originais e os commits de "retrabalho dos PRs" e de "merge" em um conjunto pequeno de commits focalizados. Criar um merge explícito para esses commits é opcional, mas tem seu valor. Ele registra quando o feature (recurso) foi passado oficialmente para a branch master.

Conclusão

Espero que essa explicação tenha dado algumas ideias sobre git merge e git rebase. As estratégias de merge e de rebase são sempre discutíveis. Talvez, porém, este artigo ajude você a clarear suas dúvidas e permita a você adotar uma abordagem que funcione para sua equipe.

Eu gostaria muito de escrever sobre fluxos de trabalho do Git e sobre conceitos do Git. Gostaria de saber de você sobre o que deseja que eu escreva a seguir.

Tudo de bom!

code = coffee + developer (código = café + desenvolvedor)

Microverse - escola de programação para desenvolvedores de software

imcvBz4swIFiLs19gCb7EiWDFbtWOA9hFGmb