Quando devo usar o git pull –rebase?

Eu conheço algumas pessoas que usam git pull --rebase por padrão e outras que insistem em nunca usá-lo. Acredito que entendi a diferença entre mesclar e rebasing, mas estou tentando colocar isso no contexto do git pull . É apenas sobre não querer ver muitas mensagens de consolidação de mesclagem, ou existem outros problemas?

Você deve usar git pull --rebase quando

  • suas mudanças não merecem um ramo separado

De fato – por que não então? É mais claro e não impõe um agrupamento lógico nos seus commits.


Ok, suponho que precisa de algum esclarecimento. No Git, como você provavelmente sabe, você é incentivado a ramificar e mesclar. Seu branch local, no qual você puxa mudanças, e branch remoto são, na verdade, branches diferentes, e git pull é sobre mesclá-los. É razoável, já que você não faz isso com muita frequência e geralmente acumula várias alterações antes de constituírem um recurso completo.

No entanto, às vezes – por qualquer motivo – você acha que seria realmente melhor se esses dois – remotos e locais – fossem um ramo. Como no SVN. É aqui que git pull --rebase entra em jogo. Você não mais se fundir – na verdade, você confirma no topo do ramo remoto . Isso é o que realmente é.

Se é perigoso ou não é a questão de saber se você está tratando ramo local e remoto como uma coisa inseparável. Às vezes é razoável (quando suas mudanças são pequenas, ou se você está no início de um desenvolvimento robusto, quando mudanças importantes são trazidas por pequenos commits). Às vezes não é (quando você normalmente criaria outro ramo, mas você estava com preguiça de fazer isso). Mas essa é uma questão diferente.

Eu gostaria de fornecer uma perspectiva diferente sobre o que “git pull –rebase” realmente significa, porque parece se perder algumas vezes.

Se você já usou o Subversion (ou CVS), você pode estar acostumado com o comportamento de “svn update”. Se você tiver alterações para confirmar e o commit falhar porque as alterações foram feitas pelo autor, você “svn update”. O Subversion procede mesclando mudanças upstream com as suas, potencialmente resultando em conflitos.

O que o Subversion acabou de fazer foi essencialmente “pull –rebase”. O ato de reformular suas alterações locais para ser relativo à versão mais nova é a parte “rebasing” dela. Se você tiver feito “svn diff” antes da tentativa de commit falhada, e depois comparar o diff resultante com a saída de “svn diff”, a diferença entre os dois diffs é o que a operação de rebasing fez.

A principal diferença entre o Git e o Subversion, neste caso, é que no Subversion, as alterações “your” existem apenas como alterações não comprometidas em sua cópia de trabalho, enquanto no Git você tem commits reais localmente. Em outras palavras, em Git você bifurcou a história; sua história e a história do upstream divergiram, mas você tem um ancestral comum.

Na minha opinião, no caso normal de ter sua filial local simplesmente refletindo a ramificação upstream e fazendo desenvolvimento contínuo nela, a coisa certa a fazer é sempre “–rebase”, porque é isso que você está semanticamente fazendo . Você e outros estão destruindo a história linear pretendida de um ramo. O fato de que alguém tenha tentado empurrar um pouco antes de sua tentativa de tentativa é irrelevante, e parece contraproducente que cada acidente de timing resulte em fusões na história.

Se você realmente sente a necessidade de algo ser um ramo por qualquer motivo, essa é uma preocupação diferente na minha opinião. Mas a menos que você tenha um desejo específico e ativo de representar suas mudanças na forma de uma mesclagem, o comportamento padrão deve, na minha opinião, ser “git pull –rebase”.

Por favor, considere outras pessoas que precisam observar e entender a história do seu projeto. Você quer o histórico repleto de centenas de fusões em todo o lugar, ou você quer apenas algumas poucas mesclas que representam verdadeiras mesclas de esforços de desenvolvimento divergentes intencionais?

Eu acho que você deveria usar git pull --rebase ao colaborar com outras pessoas no mesmo branch. Você está no seu trabalho → commit → work → ciclo de commit, e quando você decide empurrar o seu trabalho seu push é rejeitado, porque tem havido um trabalho paralelo no mesmo branch. Neste ponto eu sempre faço um pull --rebase . Eu não uso squash (para aplainar commits), mas eu rebase para evitar os commits de mesclagem extra.

À medida que seu conhecimento Git aumenta, você se vê muito mais na história do que com qualquer outro sistema de version control que usei. Se você tem uma tonelada de pequenos commits, é fácil perder o foco do quadro maior que está acontecendo no seu histórico.

Na verdade, essa é a única vez que faço o rebase (*), e o restante do meu stream de trabalho é baseado em mesclagem. Mas, desde que seus committers mais frequentes façam isso, a história parece muito melhor no final.

(*) Enquanto ministrava um curso Git, tive uma aluna me prendendo sobre isso, já que eu também defendia o rebate de filiais em certas circunstâncias. E ele leu essa resposta;) Essa rebatização também é possível, mas sempre tem que ser de acordo com um sistema pré-estabelecido / acordado e, como tal, não deve ser “sempre” aplicado. E nesse momento eu normalmente não faço pull --rebase , que é sobre o que é a questão;)

Talvez a melhor maneira de explicar isso seja com um exemplo:

  1. Alice cria o ramo de tópicos A e trabalha nele
  2. Bob cria um ramo de tópicos não relacionado B e trabalha nele
  3. Alice faz git checkout master && git pull . O mestre já está atualizado.
  4. O Bob faz o git checkout master && git pull . O mestre já está atualizado.
  5. Alice faz git merge topic-branch-A
  6. Bob faz a git merge topic-branch-B
  7. Bob faz o git push origin master antes de Alice
  8. Alice faz o git push origin master , que é rejeitado porque não é uma fusão rápida.
  9. Alice olha o log de origem / mestre e vê que o commit não tem relação com o dela.
  10. Alice faz o git pull --rebase origin master
  11. A consolidação de mesclagem de Alice é desfeita, a confirmação de Bob é extraída e o commit de Alice é aplicado após o commit de Bob.
  12. Alice faz o git push origin master , e todos estão felizes por não terem que ler um commit de mesclagem inútil quando olharem para os logs no futuro.

Observe que a ramificação específica que está sendo mesclada é irrelevante para o exemplo. O mestre neste exemplo poderia ser facilmente uma ramificação de lançamento ou uma ramificação dev. O ponto principal é que a Alice & Bob estão simultaneamente unindo suas filiais locais em uma ramificação remota compartilhada.

Eu não acho que haja alguma razão para não usar pull --rebase – eu adicionei código ao Git especificamente para permitir que meu comando git pull sempre rebase contra commits upstream.

Ao olhar através da história, nunca é interessante saber quando o cara / gal trabalhando no recurso parou para sincronizar. Pode ser útil para o cara / gal enquanto ele / ela está fazendo isso, mas é para isso que reflog é. É só adicionar ruído para todos os outros.

Apenas lembra-te:

  • pull = buscar + mesclar
  • pull –rebase = buscar + rebase

Então, escolha o jeito que você quer lidar com o seu ramo.

É melhor você saber a diferença entre mesclar e rebase 🙂

Eu acho que isso se resume a uma preferência pessoal.

Você quer esconder seus erros bobos antes de empurrar suas mudanças? Se assim for, git pull --rebase é perfeito. Ele permite que você acabe com seus commits para alguns (ou um) commits. Se você tiver mesclagens no seu histórico (não pressionado), não é tão fácil fazer um git rebase posterior.

Eu pessoalmente não me importo de publicar todos os meus erros bobos, então eu tendem a me fundir em vez de rebase.

git pull --rebase pode esconder um histórico reescrito de um colaborador git push --force . Eu recomendo usar o git pull --rebase somente se você souber que esqueceu de enviar seus commits antes que alguém faça o mesmo.

Se você não cometeu nada, mas seu espaço de trabalho não está limpo, apenas git stash antes de git pull . Dessa forma, você não rewriteá silenciosamente sua história (o que poderia silenciosamente deixar um pouco do seu trabalho).