Suponha que originalmente havia 3 commits, A, B, C:
Em seguida, o desenvolvedor Dan criou o commit De o desenvolvedor Ed criou o commit E:
Obviamente, esse conflito deve ser resolvido de alguma forma. Para isso, existem 2 maneiras:
MERGE :
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 :
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!
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 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 )
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)
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.
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.
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.
Respostas:
Suponha que originalmente havia 3 commits,
A
,B
,C
:Em seguida, o desenvolvedor Dan criou o commit
D
e o desenvolvedor Ed criou o commitE
:Obviamente, esse conflito deve ser resolvido de alguma forma. Para isso, existem 2 maneiras:
MERGE :
Ambos confirmam
D
eE
ainda estão aqui, mas criamos um commit de mesclagemM
que herda mudanças de ambosD
eE
. No entanto, isso cria uma forma de diamante , que muitas pessoas acham muito confusa.REBASE :
Criamos commit
R
, cujo conteúdo real do arquivo é idêntico ao do commit de mesclagemM
acima. Mas nos livramos do commitE
, como se ele nunca tivesse existido (indicado por pontos - linha de fuga). Devido a essa obliteração,E
deve 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!fonte
git merge
não intercala as confirmações (mas pode parecer assimgit log
). Em vez disso,git merge
manté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 rebase
faz parecer que Dan trabalhou primeiro e Ed o seguiu. Nos dois casos (mesclagem e rebase), a árvore de arquivos resultante real é absolutamente idêntica.Eu realmente amo esse trecho de 10 coisas que eu odeio no git (ele fornece uma breve explicação para rebase no segundo exemplo):
E então nós temos
o que é uma boa descrição.
1. sem censura no original
fonte
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:
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:
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:
Todos os seus commits estão na parte superior (mais recente), seguidos pelo restante da
master
ramificação.( Aviso: sou o autor da postagem "10 coisas que odeio no Git" mencionada em outra resposta )
fonte
Embora a resposta aceita e a mais votada sejam ótimas, também acho útil tentar explicar a diferença apenas com palavras:
fundir
rebase
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)
fonte
A rebase do Git está mais próxima de uma mesclagem. A diferença na rebase é:
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.
fonte
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.
fonte
Encontrei um artigo realmente interessante sobre git rebase vs merge , pensei em compartilhá-lo aqui
fonte