Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Rebasing avanzato in Git

Come eseguire il rabasing, e il successivo merging, in un progetto dal quale sono stati generati più rami tenendo conto delle modifiche apportate ad essi.
Come eseguire il rabasing, e il successivo merging, in un progetto dal quale sono stati generati più rami tenendo conto delle modifiche apportate ad essi.
Link copiato negli appunti

Abbiamo visto come in Git il rebasing applica le modifiche rispettando l'ordine con le quali sono state effettuate, ciò avviene senza la necessità di creare commit di fusione come invece accade nel caso del merging. Quali sono i vantaggi del rebasing nella gestione di più rami generati dal medesimo master? Come gestire più rami con cronologie differenti?

Rebasing su rami multipli

Ora immaginiamo di sviluppare un progetto che potrebbe essere, per esempio, un'applicazione per la messaggistica istantanea che supporta sia le comunicazioni testuali che le chiamate vocali.

Figura 1. Inizializzazione del progetto.
Creazione del progetto

Queste due funzionalità potrebbero essere implementate in due rami differenti entrambi derivati dal master, ipotizziamo quindi di avere un ramo "text" dedicato alla prima e un secondo ramo chiamato "call".

Figura 2. Generazione dei rami.
Generazione dei rami

Sempre rimanendo nel campo delle ipotesi, una volta apportata una modifica a "text" possiamo confermarla tramite commit per poi cominciare a lavorare su "call" spostando il puntatore su di esso, apportati dei cambiamenti anche a quest'ultimo li confermiamo con degli ulteriori commit per poi tornare a "text". Altre modifiche a "text" si traducono quindi in commit aggiuntivi.

Riassumendo: abbiamo prima modificato "text", poi siamo intervenuti su "call" e infine abbiamo apportato ulteriori cambiamenti a "text". Tutto è stato confermato con dei commit. Abbiamo dunque due rami e due diverse cronologie.

Figura 3. Modifiche sui rami e commit.
Modifiche sui rami e commit

A questo punto uno dei rami implementati potrebbe essere pronto per la fase di deployment, mettiamo "call", mentre "text" potrebbe necessitare di ulteriori verifiche e non essere pronto per la distribuzione. Come fare? La logica ci suggerisce di unire soltanto "call" al master, quindi una soluzione ottimale potrebbe essere quella di unire al master esclusivamente le modifiche di "call" non presenti in "text".

Ciò è possibile passando al comando git rabase l'opzione --onto seguita da tre parametri: il nome del ramo principale, cioè il master, il nome del ramo da non unire allo stato corrente, "text", e quello del ramo che dovrà essere unito al master escludendo le modifiche comuni con il precedente, "call".

Nel caso del nostro progetto possiamo quindi utilizzare un'istruzione come la seguente:

$ git rebase --onto master text call

Traducendo quanto digitato, stiamo in pratica ordinando a Git di prendere il ramo "call" considerando soltanto le componenti comuni con "text" e di procedere all'unione con il master.

Merging post rebasing

Fatto questo non abbiamo più bisogno di "call" perché le modifiche apportare ad esso sono presenti in master in quanto unite al suo flusso di lavoro, sostanzialmente abbiamo spostato il puntatore di master fino all'ultimo cambiamento eseguito su "call". Possiamo quindi procedere con il merging tra "call" e master:

$ git checkout master
$ git merge call

Perché effettuare anche questa operazione oltre al rebasing? Perché in questo modo otteniamo un ramo, master, il principale, in cui la cronologia di "call" e "master" coincidono in un unico flusso di lavoro.

Figura 4. Rebasing e merging di un ramo.
Rebasing e merging di un ramo

Ora, come riallineare la cronologia di "text" a master una volta effettuato il merging di "call"? A questo punto, avendo già allineato "call" al master, possiamo procedere con il rabasing di "text" in master senza dover tenere conto delle modifiche apportate ad un ulteriore ramo. Non abbiamo quindi la necessità dell'opzione --onto:

$ git rebase master text

Una volta rifondato "text" in master, "text" può quindi essere fuso in master:

$ git checkout master
$ git merge text

I flussi di lavoro di "call" e "text" sono quindi entrambi allineati con quello del master ed è disponibile un'unica cronologia, che rispetta l'ordine delle modifiche effettuate, per tutto il nostro progetto. Non rimane altro che cancellare i due rami derivati divenuti ormai inutili:

$ git branch -d call
$ git branch -d text

Immaginiamo di inserire una dinamica simile all'interno di un progetto sviluppato da più collaboratori, ognuno impegnato nell'implementazione di una specifica funzionalità. Grazie al rebasing possiamo sincronizzare più flussi di lavoro rispettando la cronologia di tutti i cambiamenti effettuati, senza alcuna sovrapposizione.

Ti consigliamo anche