Che cos'è Git Rebase e in cosa è diverso dall'unione?

0
276

L'unione e il rebasing raggiungono obiettivi simili, ma perseguirli in modi diversi. Entrambi aiutano a gestire il lavoro con le filiali e la collaborazione con più persone, ma non sono intercambiabili e il rebase può essere dannoso se non eseguito correttamente.

Qual è il problema con il rebasing?

Il rebasing è molto complicato, quindi è importante capire come funziona git sotto il cofano se vogliamo capirlo .

Git memorizza il tuo codice come una serie di modifiche. Puoi pensare a questo come una catena, lavorando all'indietro. Ogni modifica o “commit,” fa riferimento all'ID del commit precedente e include ciò che è cambiato rispetto al commit precedente. Questa catena è memorizzata solo sul tuo computer; il tuo client Git non parla con nessun altro client Git a meno che non stia eseguendo un fetch o push (pull è in realtà solo fetch + merge con la tua filiale locale), e anche in questo caso, sta solo parlando a un repository remoto condiviso.

I rami sono più complicati. Git memorizza solo una cosa quando si tratta di branch: l'ID del commit alla fine del branch. In questo modo, puoi immaginarli come la testina di riproduzione su un giradischi; metti la testa del ramo in una posizione specifica e torna indietro attraverso la catena, “suonando” il tuo codice e arrivare a una versione finale. Ogni volta che esegui il commit, il tuo client git locale sposterà automaticamente l'indicatore di riproduzione in avanti al nuovo commit.

Se volessi unire le funzionalità in master, esegui:

git checkout master git merge feature Pubblicità

Questo crea un nuovo commit di unione e, se ci sono conflitti, dovrai risolverli manualmente. Il comando git merge sposta l'indicatore di riproduzione principale sul nuovo commit di unione ed elimina l'indicatore di riproduzione della funzione, poiché non è più necessario.

Questo metodo di fusione del codice presenta tre problemi:

  • Potrebbero esserci cambiamenti sia sul ramo principale che sul ramo delle funzionalità vorrei includere, in particolare se la funzionalità richiede tempo per lo sviluppo.
  • Essere costretti a eseguire il processo di unione ogni volta che si desidera lavorare con i rami è fastidioso.
  • La cronologia dei commit è disordinata, anche se questo è in gran parte un problema estetico.

Rebasing cerca di risolvere questi problemi, con vari gradi di successo. Ribasare le modifiche dove hai iniziato il tuo ramo. L'intero ramo viene sollevato e trasportato alla fine del ramo master corrente, dove si collega alla fine. Il ramo principale non viene toccato ed è libero di continuare a ricevere commit.

I commit non vengono effettivamente spostati, tuttavia, poiché i commit sono immutabili. Piuttosto, vengono copiati, il che si traduce in nuovi ID di commit. I commit precedenti vengono lasciati bloccati, nascosti nei tuoi file Git ma non vengono mai più visti, poiché l'indicatore di riproduzione si è spostato da qualche altra parte.

Per eseguire questo processo dalla riga di comando, esegui:

funzione git checkout git pull git rebase master

Questo apre il ramo, carica le modifiche correnti in master e quindi ribasa il ramo della funzionalità sul ramo principale.

A questo punto, il codice nel ramo della funzionalità è ora più aggiornato, che è il unica vera caratteristica di git rebase. Il rebasing non unisce i rami, poiché non crea alcun commit di unione o sposta l'indicatore di riproduzione del master.

Se vuoi unire dopo il rebasing, esegui:

git checkout master git merge funzionalità Pubblicità

Che sarebbe simile a questo, con l'indicatore di riproduzione principale che sostituisce l'indicatore di riproduzione della funzione:

Quindi il rebasing non finisce per risolvere il problema di gestire le unioni, dal momento che dovrai comunque eseguire l'unione alla fine per aggiornare il ramo principale. Tuttavia, l'effettivo comando di unione alla fine dovrebbe essere eseguito senza intoppi, poiché il processo di rebase richiede di “unire” nei cambiamenti, che possono ancora causare conflitti. E se desideri continuare a lavorare sul tuo ramo, devi comunque “unire” nelle modifiche.

Non ribasare i rami condivisi

Ricordi come la ribasatura delle copie esegue il commit e lascia una testina di riproduzione bloccata? Questo è in realtà un grosso problema se stai lavorando con codice condiviso. Supponiamo che tu abbia creato il branch della funzionalità e lo inserisca nel tuo repository in modo che i tuoi colleghi possano testarlo. Va tutto bene, ma se uno di loro volesse diramarsi dal tuo ramo, quando alla fine esegui il rebase, finisci con questo:

Il branch feature2 del tuo collega ora fa riferimento a una vecchia catena di commit. Il tuo client Git non ha modo di saperlo, dal momento che il ramo feature2 è memorizzato sul computer del tuo collega. Inoltre, non hanno modo di sapere che hai ribasato finché non invii le modifiche.

Quando hai ribasato, non ha copiato il ramo feature2 quando ha copiato tutti i commit. Anche se potesse, non influenzerebbe il repository Git locale del tuo collega, rendendo tutto non sincronizzato. La soluzione qui sarebbe quella di ribasare feature2 su feature nel punto in cui si troverebbe, ma questo è disordinato, anche per gli standard Git, e questo è solo un esempio molto semplice.

In conclusione è, non eseguire il rebase se non stai lavorando localmente.

Quando è meglio ribasare che unire?

Se il tuo ramo richiederà un po' di tempo per svilupparsi, il rebase risolve il problema della “sindrome del ramo,” dove il tuo codice è troppo obsoleto con il master funzionante e devi aggiornarlo per continuare a lavorare. Parlando in generale, dovresti cercare di evitare questo problema il più possibile, ma il rebase può risolverlo quando si presenta.

Pubblicità

Se stai solo apportando piccole modifiche giornaliere incrementali, dovresti invece lavorare su un ramo principale locale e utilizzare le richieste pull quando sei pronto per inviare le modifiche. Questi utilizzano il modello dei rami topici, creato appositamente per memorizzare il codice prima che venga approvato per un'unione.

Ma, se stai lavorando su un intervallo di tempo settimanale e stai per finisci per fare più richieste pull e unire più volte, puoi lavorare sul tuo codice un po' più a lungo, eseguire il rebase localmente per gli aggiornamenti ed eseguire una richiesta pull alla fine per ridurre la quantità di test e parlare con i supervisori. Il rebase è principalmente una cosa locale, quindi puoi farlo sui tuoi branch di staging senza aspettare l'approvazione.

Se nessun altro dipende dal tuo branch, puoi rebase prima che un branch si unisca per rendere la cronologia dei commit pulita e unidimensionale. Tuttavia, si potrebbe obiettare che la fusione tradizionale, sebbene certamente più brutta, è più facile da seguire e da eseguire il debug, poiché i commit di unione sono completamente non distruttivi. In entrambi i casi, la ribasatura deve essere eseguita subito prima che le modifiche vengano unite, oppure potresti riscontrare il problema dell'aggiornamento del Master prima che le modifiche vengano approvate.