Qual é a diferença entre 'git merge' e 'git rebase'?


499

Qual é a diferença entre git mergee git rebase?


14
desde a minha resposta foi apagado, visite este link para obter a resposta certa para esta pergunta: git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase
HiB

6
A propósito, vou adicionar este site. Tudo o que você precisa saber sobre o git learn jogando: pcottle.github.io/learnGitBranching
Rollyng

Leia isto primeiro: git-scm.com/book/en/v2/… Então: git-scm.com/book/en/v2/Git-Branching-Rebasing Você realmente entenderá.
Liber

Respostas:


867

Suponha que originalmente havia 3 commits, A, B, C:

abc

Em seguida, o desenvolvedor Dan criou o commit De o desenvolvedor Ed criou o commit E:

ABCDE

Obviamente, esse conflito deve ser resolvido de alguma forma. Para isso, existem 2 maneiras:

MERGE :

ABCDEM

Ambos confirmam De Eainda estão aqui, mas criamos um commit de mesclagem Mque herda mudanças de ambos De E. No entanto, isso cria uma forma de diamante , que muitas pessoas acham muito confusa.

REBASE :

ABCDER

Criamos commit R, cujo conteúdo real do arquivo é idêntico ao do commit de mesclagem Macima. Mas nos livramos do commit E, como se ele nunca tivesse existido (indicado por pontos - linha de fuga). Devido a essa obliteração, Edeve ser local para o desenvolvedor Ed e nunca deve ter sido enviado para nenhum outro repositório. A vantagem da rebase é que a forma do diamante é evitada e a história permanece em linha reta - a maioria dos desenvolvedores adora isso!


53
Boas ilustrações. No entanto, eu não concordo plenamente com o tom positivo de que o rebase é tratado. Tanto na mesclagem quanto na rebase, podem ocorrer conflitos que precisam de resolução manual. E como sempre, quando programadores estão envolvidos, há uma chance não negligenciável de erros, também conhecidos como bugs. Se ocorrer um erro de mesclagem, toda a equipe ou comunidade poderá ver a mesclagem e verificar se um bug foi introduzido lá. A história da rebase permanece no repositório de um desenvolvedor e, mesmo lá, tem vida útil limitada no reflog. Pode parecer melhor, mas ninguém mais pode ver com facilidade o que deu errado.
Uwe Geuder

> "No entanto, isso cria um formato de diamante, que muitas pessoas acham muito confuso." Hum ... você pode elaborar?
9788 Greg Maletic

@GregMaletic: A forma do diamante é uma história não linear. Não sei você, mas não gosto de coisas não lineares em geral. Dito isto, você pode usar a mesclagem com diamantes, se você realmente preferir - ninguém está forçando você.
mvp

1
Embora essa resposta seja extremamente útil, seria melhor se você adicionasse comandos reais do git com arquivos foo.txt simples para reproduzi-lo localmente. Como o último usuário disse, não é óbvio quem está fazendo o rebase.
Vortex

1
@ pferrel: acho que você não entendeu direito. git mergenão intercala as confirmações (mas pode parecer assim git log). Em vez disso, git mergemantém os dois históricos de desenvolvimento de Dan e Ed preservados intactos, como foi visto de cada ponto de vista de cada vez. git rebasefaz parecer que Dan trabalhou primeiro e Ed o seguiu. Nos dois casos (mesclagem e rebase), a árvore de arquivos resultante real é absolutamente idêntica.
Mvp

158

Eu realmente amo esse trecho de 10 coisas que eu odeio no git (ele fornece uma breve explicação para rebase no segundo exemplo):

3. Documentação de baixa qualidade

As páginas de manual são um todo-poderoso "f *** you" 1 . Eles descrevem os comandos da perspectiva de um cientista da computação, não de um usuário. Caso em questão:

git-push – Update remote refs along with associated objects

Aqui está uma descrição para humanos:

git-push – Upload changes from your local repository into a remote repository

Atualização, outro exemplo: (obrigado cgd)

git-rebase – Forward-port local commits to the updated upstream head

Tradução:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

E então nós temos

git-merge - Join two or more development histories together

o que é uma boa descrição.


1. sem censura no original


O problema não é a linguagem ou se o usuário é um cientista da computação ou não. Embora reformulá-lo de outra maneira ajude a esclarecer os fins (ou seja, o que acontece), ele falha em explicar os meios (como acontece). Git requer entender os meios para entender os fins. É entender precisamente os meios que tornam o Git tão difícil. Como ferramenta, algo usado para simplificar ou reduzir o esforço necessário na tarefa, o Git falha terrivelmente. Infelizmente, muitos desenvolvedores não conseguem perceber isso.
ATL_DEV

128

Pessoalmente, não acho muito útil a técnica de diagramação padrão - as setas sempre parecem apontar o caminho errado para mim. (Eles geralmente apontam para o "pai" de cada confirmação, que acaba atrasando o tempo, o que é estranho).

Para explicar em palavras:

  • Quando você refaz seu ramo para o ramo dele, você diz ao Git para fazer com que pareça que você fez check-out do ramo deles de forma limpa e depois fez todo o seu trabalho a partir daí. Isso cria um pacote limpo e conceitualmente simples de alterações que alguém pode revisar. Você pode repetir esse processo novamente quando houver novas alterações em suas ramificações e sempre terá um conjunto limpo de alterações "na ponta" de suas ramificações.
  • Quando você mescla o ramo deles no ramo, você amarra os dois históricos de galhos nesse momento. Se você fizer isso novamente mais tarde com mais alterações, começará a criar um encadeamento de histórias intercaladas: algumas de suas mudanças, algumas de minhas mudanças, algumas de suas mudanças. Algumas pessoas acham isso confuso ou indesejável.

Por razões que não entendo, as ferramentas da GUI para o Git nunca fizeram muito esforço para apresentar os históricos de mesclagem de maneira mais limpa, abstraindo as mesclagens individuais. Portanto, se você quiser um "histórico limpo", precisará usar o rebase.

Lembro-me de ter lido postagens de blog de programadores que usam apenas rebase e outros que nunca usam rebase.

Exemplo

Vou tentar explicar isso com um exemplo de apenas palavras. Digamos que outras pessoas em seu projeto estejam trabalhando na interface do usuário e você esteja escrevendo documentação. Sem rebase, seu histórico pode ser algo como:

Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

Ou seja, mescla e a confirmação da interface do usuário no meio da confirmação da documentação.

Se você reformulou seu código para mestre em vez de mesclá-lo, seria assim:

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

Todos os seus commits estão na parte superior (mais recente), seguidos pelo restante da masterramificação.

( Aviso: sou o autor da postagem "10 coisas que odeio no Git" mencionada em outra resposta )


42

Embora a resposta aceita e a mais votada sejam ótimas, também acho útil tentar explicar a diferença apenas com palavras:

fundir

  • “Tudo bem, temos dois estados desenvolvidos diferentemente do nosso repositório. Vamos fundi-los juntos. Dois pais, um filho resultante.

rebase

  • “Dê as alterações do ramo principal (qualquer que seja o nome) no meu ramo de recursos. Faça isso fingindo que meu trabalho de destaque começou mais tarde, de fato no estado atual da ramificação principal. ”
  • "Reescreva o histórico das minhas alterações para refletir isso." (é necessário forçá-los a forçar, porque normalmente o controle de versão não interfere no histórico fornecido)
  • “Provavelmente - se as mudanças que eu fiz teve pouco a ver com o meu trabalho - a história realmente não mudará muito, se eu olhar para meus commits diff por diff (você também pode pensar em 'patches').”

resumo: quando possível, o rebase é quase sempre melhor. Facilitando a reintegração ao ramo principal.

Porque? ➝ seu ​​trabalho de recurso pode ser apresentado como um grande 'arquivo de correção' (também conhecido como diff) em relação à ramificação principal, sem a necessidade de 'explicar' vários pais: pelo menos dois, provenientes de uma mesclagem, mas provavelmente muitos mais, se houver houve várias fusões. Diferentemente das mesclagens, várias rebotes não são adicionadas. (outra grande vantagem)


18

A rebase do Git está mais próxima de uma mesclagem. A diferença na rebase é:

  • as confirmações locais são removidas temporariamente da ramificação.
  • executar o git pull
  • insira novamente todos os seus commits locais.

Isso significa que todas as confirmações locais são movidas para o final, depois de todas as confirmações remotas. Se você tiver um conflito de mesclagem, também precisará resolvê-lo.


7

Para facilitar a compreensão pode ver a minha figura.

O rebase mudará o hash de confirmação, de modo que, se você quiser evitar muito conflito, use rebase quando o ramo estiver concluído / completo como estável.

insira a descrição da imagem aqui


0

Encontrei um artigo realmente interessante sobre git rebase vs merge , pensei em compartilhá-lo aqui

  • Se você quiser ver o histórico completamente igual ao ocorrido, use a mesclagem. A mesclagem preserva o histórico, enquanto a reorganização o reescreve.
  • A mesclagem adiciona um novo commit ao seu histórico
  • É melhor rebasear para otimizar um histórico complexo, você pode alterar o histórico de consolidação por rebase interativa.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.