Qual è la differenza tra 'git merge' e 'git rebase'?


499

Qual è la differenza tra git mergee git rebase?


14
da quando la mia risposta è stata cancellata, visita questo link per ottenere la risposta giusta a questa domanda: git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase
Ciao

6
A proposito, aggiungerò questo sito. Tutto quello che devi sapere su Git
Learn


Risposte:


867

Supponiamo che in origine erano 3 commit, A, B, C:

ABC

Quindi lo sviluppatore Dan ha creato il commit De lo sviluppatore Ed ha creato il commit E:

ABCDE

Ovviamente, questo conflitto dovrebbe essere risolto in qualche modo. Per questo, ci sono 2 modi:

MERGE :

ABCDEM

Entrambi eseguono il commit De Esono ancora qui, ma creiamo un commit di unione Mche eredita le modifiche da entrambi De E. Tuttavia, questo crea una forma di diamante , che molte persone trovano molto confusa.

REBASE :

ABCDER

Creiamo commit R, il cui contenuto effettivo è identico a quello di merge commit Msopra. Ma ci liberiamo del commit E, come se non fosse mai esistito (indicato da punti - linea di fuga). A causa di questa cancellazione, Edovrebbe essere locale allo sviluppatore Ed e non avrebbe mai dovuto essere trasferito in nessun altro repository. Il vantaggio di rebase è che si evita la forma di un diamante e la storia rimane in linea retta - la maggior parte degli sviluppatori lo adora!


53
Belle illustrazioni. Tuttavia, non sono pienamente d'accordo con il tono positivo che viene gestito il rebase. In entrambi i casi si possono verificare conflitti che richiedono una risoluzione manuale. E come sempre quando i programmatori sono coinvolti, c'è una possibilità non trascurabile di errori, noti anche come bug. Se si verifica un errore di unione, l'intero team o la comunità possono vedere l'unione e verificare se un bug è stato introdotto lì. La storia del rebase rimane nel repository di 1 sviluppatore e anche lì ha solo una durata limitata nel reflog. Potrebbe sembrare più bello, ma nessun altro può vedere così facilmente cosa è andato storto.
Uwe Geuder,

> "Tuttavia, questo crea una forma di diamante, che molte persone trovano molto confusa." Um ... puoi elaborare?
Greg Maletic,

@GregMaletic: la forma del diamante è una storia non lineare. Non ti conosco, ma non mi piacciono le cose non lineari in generale. Detto questo, sei il benvenuto a usare l'unione con i diamanti se lo preferisci davvero - nessuno ti sta forzando.
mvp,

1
Sebbene questa risposta sia estremamente utile, sarebbe meglio se si aggiungessero comandi git effettivi con semplici file foo.txt per riprodurli localmente. Come ha detto l'ultimo utente, non è ovvio chi stia facendo rebase.
Vortice,

1
@pferrel: non penso di averlo capito correttamente. git mergenon interleave si impegna (ma potrebbe apparire così guardando git log). Invece, git mergemantiene intatte entrambe le storie di sviluppo di Dan ed Ed, come è stato visto da ogni punto di vista alla volta. git rebasesembra che Dan ci abbia lavorato prima, ed Ed lo ha seguito. In entrambi i casi (unione e rebase), l'albero dei file risultante effettivo è assolutamente identico.
MVP

158

Adoro questo estratto di 10 cose che odio di Git (fornisce una breve spiegazione di rebase nel suo secondo esempio):

3. Documentazione scadente

Le pagine man sono un'onnipotente "fottuta" 1 . Descrivono i comandi dal punto di vista di un informatico, non di un utente. Caso in questione:

git-push – Update remote refs along with associated objects

Ecco una descrizione per l'uomo:

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

Aggiornamento, un altro esempio: (grazie cgd)

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

Traduzione:

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

E poi abbiamo

git-merge - Join two or more development histories together

che è una buona descrizione.


1. senza censure nell'originale


Il problema non è la lingua o se l'utente è un informatico o meno. Mentre la riformulazione in un altro modo aiuta a chiarire i fini (cioè che cosa succede), non riesce a spiegare i mezzi (come succede). Git richiede la comprensione dei mezzi per comprendere i fini. Comprende esattamente i mezzi che rendono Git così difficile. Come strumento, qualcosa usato per semplificare o ridurre lo sforzo richiesto nel compito, Git fallisce orribilmente. Purtroppo, troppi sviluppatori non riescono a realizzarlo.
ATL_DEV,

128

Personalmente non trovo molto utile la tecnica del diagramma standard: le frecce sembrano sempre indicare la direzione sbagliata per me. (Indicano generalmente il "genitore" di ogni commit, che finisce per essere indietro nel tempo, il che è strano).

Per spiegarlo a parole:

  • Quando rinnovi il tuo ramo sul loro ramo, dici a Git di farlo sembrare come se avessi controllato il loro ramo in modo pulito, quindi hai fatto tutto il tuo lavoro a partire da lì. Ciò rende un pacchetto di modifiche pulito e concettualmente semplice che qualcuno può rivedere. Puoi ripetere di nuovo questo processo quando ci sono nuove modifiche sul loro ramo e finirai sempre con un set pulito di modifiche "sulla punta" del loro ramo.
  • Quando unisci il loro ramo nel tuo ramo, a questo punto leghi le due storie del ramo. Se lo fai di nuovo più tardi con più modifiche, inizi a creare un thread interlacciato di storie: alcune delle loro modifiche, alcune delle mie modifiche, alcune delle loro modifiche. Alcune persone lo trovano disordinato o indesiderabile.

Per motivi che non capisco, gli strumenti della GUI per Git non hanno mai fatto uno sforzo per presentare le storie di unione in modo più pulito, astraggendo le singole fusioni. Quindi, se si desidera una "cronologia pulita", è necessario utilizzare rebase.

Mi sembra di ricordare di aver letto post sul blog di programmatori che usano solo rebase e altri che non usano mai rebase.

Esempio

Proverò a spiegarlo con un esempio di sole parole. Supponiamo che altre persone nel tuo progetto stiano lavorando sull'interfaccia utente e tu stia scrivendo documentazione. Senza rebase, la tua storia potrebbe assomigliare a:

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

Cioè, le fusioni e l'interfaccia utente si impegnano nel mezzo dei commit della documentazione.

Se hai riformulato il codice su master invece di unirlo, sembrerebbe così:

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

Tutti i tuoi commit sono in alto (i più recenti), seguiti dal resto della masterfiliale.

( Dichiarazione di non responsabilità: sono l'autore del post "10 cose che odio di Git" a cui fa riferimento in un'altra risposta )


42

Mentre la risposta accettata e più votata è ottima, trovo inoltre utile cercare di spiegare la differenza solo a parole:

merge

  • “Va bene, abbiamo ottenuto due stati sviluppati diversamente nel nostro repository. Uniamoli insieme. Due genitori, un figlio che ne risulta. "

rebase

  • “Dai le modifiche del ramo principale (qualunque sia il suo nome) al mio ramo di funzione. Fallo fingendo che il mio lavoro sia iniziato più tardi, in effetti sullo stato attuale del ramo principale. "
  • "Riscrivi la cronologia delle mie modifiche per riflettere ciò." (è necessario forzarli, perché normalmente il controllo delle versioni consiste nel non manomettere la cronologia fornita)
  • "Probabilmente —se i cambiamenti in cui ho elaborato hanno poco a che fare con il mio lavoro— la storia in realtà non cambierà molto, se guardo i miei commit differ per diff (potresti anche pensare a 'patch').“

riepilogo: quando possibile, rebase è quasi sempre migliore. Semplificare la reintegrazione nel ramo principale.

Perché? ➝ il tuo lavoro di funzionalità può essere presentato come un grande 'file patch' (aka diff) rispetto al ramo principale, senza dover 'spiegare' più genitori: almeno due, provenienti da una fusione, ma probabilmente molti altri, se presenti sono state diverse fusioni. A differenza delle fusioni, più rebase non si sommano. (un altro grande vantaggio)


18

Git rebase è più vicino a un'unione. La differenza in rebase è:

  • i commit locali vengono rimossi temporaneamente dal ramo.
  • esegui git pull
  • inserisci di nuovo tutti i tuoi commit locali.

Ciò significa che tutti gli commit locali vengono spostati alla fine, dopo tutti gli commit remoti. Se hai un conflitto di unione, devi risolverlo anche tu.


7

Per una facile comprensione può vedere la mia figura.

Rebase cambierà l'hash di commit, quindi se vuoi evitare gran parte del conflitto, usa rebase quando quel ramo è fatto / completo come stabile.

inserisci qui la descrizione dell'immagine


0

Ho trovato un articolo davvero interessante su git rebase vs merge , pensato di condividerlo qui

  • Se vuoi vedere la cronologia completamente uguale a quella avvenuta, dovresti usare unisci. Unisci conserva la storia mentre rebase la riscrive.
  • La fusione aggiunge un nuovo commit alla tua cronologia
  • Rebasing è meglio semplificare una cronologia complessa, sei in grado di modificare la cronologia del commit mediante rebase interattivo.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.