Git rebase: tutto quello che c'è da sapere
Pubblicato: 2022-12-15 Il comando Git rebase
combina due rami del codice sorgente in uno solo. Anche il comando Git merge
fa questo. Spieghiamo cosa fa rebase
, come viene utilizzato e quando invece utilizzare merge
.
L'esplosione di Git
Cos'è l'unione di Git?
Cos'è il rebase di Git?
Come ribasare su un altro ramo
Git Rebase vs. Merge: quale dovresti usare?
Ribasare o non ribasare?
L'esplosione di Git
Frustrato da altri sistemi di controllo di versione e dai loro lenti aggiornamenti e commit, Linus Torvalds, famoso per il kernel Linux, ha messo da parte un mese nel 2005 per scrivere il proprio. Lo ha chiamato Git.
Siti come GitHub, GitLab e BitBucket hanno promosso e beneficiato simbioticamente di Git. Oggi Git è utilizzato a livello globale, con un enorme 98% di 71mila intervistati in un sondaggio del 2022 che utilizza Git come sistema di controllo della versione.
Una delle principali decisioni di progettazione di Git è stata la velocità. In particolare, lavorare con le filiali doveva essere il più veloce possibile. I rami sono una parte fondamentale dei sistemi di controllo della versione. Un repository di progetto avrà un ramo principale o principale. Qui è dove si trova la base di codice del progetto. Lo sviluppo, come le nuove funzionalità, avviene in rami secondari separati. Ciò impedisce al lavoro svolto nei rami di incasinare il ramo principale e consente lo sviluppo simultaneo in diverse parti della base di codice.
Man mano che gli sviluppi nei rami secondari vengono completati, le modifiche vengono trasferite al ramo principale unendo il ramo di sviluppo nel ramo principale. In altre versioni i sistemi di controllo che lavorano con i rami erano difficili e computazionalmente costosi. Lavorare con i rami in Git è molto veloce e molto leggero. Quello che una volta era un esercizio noioso e spesso evitato in altri sistemi, è diventato banale in Git.
Il comando Git rebase
è un altro modo per trasferire le modifiche da un ramo a un altro ramo. I comandi merge
e rebase
hanno obiettivi simili, ma raggiungono i loro scopi in modi diversi e producono risultati leggermente diversi.
Cos'è l'unione di Git?
Allora a cosa serve il comando Git merge
? Supponiamo che tu abbia creato un ramo chiamato dev-branch
per lavorare su una nuova funzionalità.
Fai alcuni commit e provi la tua nuova funzionalità. Funziona tutto bene. Ora vuoi inviare la tua nuova funzione al ramo master
. Devi essere nel ramo master
per unirne un altro.
Possiamo assicurarci di essere nel ramo master
controllandolo esplicitamente prima di unirci.
maestro di checkout git
Ora possiamo dire a Git di fondere il dev-branch
nel ramo corrente, che è il ramo master
.
git merge dev-branch
La nostra merge
è completata per noi. Se controlli il ramo master
e lo compili, conterrà la funzionalità appena sviluppata. Ciò che Git ha effettivamente eseguito è un'unione a tre vie. confronta i commit più recenti nei rami master
e dev-branch
e il commit nel ramo master
immediatamente prima della creazione dev-branch
. Quindi esegue un commit sul ramo master
.
Le unioni sono considerate non distruttive perché non eliminano nulla e non modificano la cronologia di Git. Il dev-branch
esiste ancora e nessuno dei commit precedenti viene modificato. Viene creato un nuovo commit che acquisisce i risultati dell'unione a tre vie.
Dopo l'unione, il nostro repository Git si presenta come una timeline con una linea alternativa che si dirama e poi ritorna alla timeline principale.
Il dev-branch
è stato incorporato nel ramo master
.
Se hai molti rami in un progetto, la cronologia del progetto può diventare confusa. Questo è spesso il caso se un progetto ha molti contributori. Poiché lo sforzo di sviluppo si suddivide in molti percorsi diversi, la cronologia dello sviluppo non è lineare. Districare la cronologia dei commit diventa ancora più difficile se i rami hanno i propri rami.
Nota che se hai modifiche non salvate nel ramo master
, dovrai fare qualcosa con queste modifiche prima di poter unire qualsiasi cosa ad esso. Potresti creare un nuovo ramo e confermare le modifiche lì, quindi eseguire l'unione. Dovresti quindi unire nuovamente il tuo ramo temporaneo nel ramo principale.
Funziona, ma Git ha un comando che ottiene la stessa cosa, senza dover creare nuovi rami. Il comando stash
memorizza le modifiche non salvate per te e ti consente di richiamarle con stash pop
.
Li useresti così:
scorta git merge dev-branch schiocco di scorta
Il risultato finale è un ramo unito, con le modifiche non salvate ripristinate.
Cos'è il rebase di Git?
Il comando Git rebase
raggiunge i suoi obiettivi in un modo completamente diverso. Prende tutti i commit dal ramo che stai per ribasare e li riproduce alla fine del ramo su cui stai ribasando.
Prendendo il nostro esempio precedente, prima di eseguire qualsiasi azione il nostro repository Git si presenta così. Abbiamo un ramo chiamato dev-branch
e vogliamo spostare quelle modifiche al ramo master
.
Dopo il rebase
, sembra un'unica linea temporale di modifiche completamente lineare.
Il dev-branch
è stato rimosso e i commit nel dev-branch
sono stati aggiunti al ramo master. Il risultato finale è lo stesso che se i commit nel dev-branch
fossero stati effettivamente impegnati direttamente nel ramo master
in primo luogo. I commit non vengono semplicemente aggiunti al ramo master
, ma vengono "riprodotti" e aggiunti di nuovo.
Questo è il motivo per cui il comando rebase
è considerato distruttivo. Il ramo ribasato non esiste più come ramo separato e la cronologia Git del tuo progetto è stata riscritta. Non è possibile determinare in un secondo momento quali commit sono stati originariamente effettuati su dev-branch
.
Tuttavia, ti lascia con una storia semplificata, lineare. Rispetto a un repository con dozzine o addirittura centinaia di rami e fusioni, leggendo il registro Git o utilizzando una GUI grafica git per guardare un grafico del repository, un repository ribasato è un gioco da ragazzi da capire.
Come ribasare su un altro ramo
Proviamo un esempio di git rebase
. Abbiamo un progetto con un ramo chiamato new-feature
. rebase
quel ramo sul ramo master
in questo modo.
Innanzitutto, controlliamo che il ramo master
non abbia modifiche in sospeso.
stato git
Controlliamo il ramo delle new-feature
.
git checkout nuova funzionalità
Diciamo a Git di rebase
il ramo corrente sul ramo master.
git rebase master
Possiamo vedere che abbiamo ancora due rami.
ramo git
Torniamo al ramo master
maestro di checkout git
Uniamo il ramo new-feature nel ramo corrente, che nel nostro caso è il ramo master
.
git merge nuova funzionalità
È interessante notare che abbiamo ancora due rami dopo la fusione finale.
La differenza è che ora l'head del ramo new-feature
e l'head del branch master
sono impostati per puntare allo stesso commit, e la cronologia di Git non mostra che prima c'era un ramo new-feature
separato, a parte l'etichetta del ramo.
Git Rebase vs. Merge: quale dovresti usare?
Non è un caso di rebase
vs. merge
. Sono entrambi comandi potenti e probabilmente li userai entrambi. Detto questo, ci sono casi d'uso in cui rebase
non funziona molto bene. Gli errori di unpicking causati da errori che utilizzano merge
sono spiacevoli, ma gli errori di unpicking causati da rebase
sono infernali.
Se sei l'unico sviluppatore che utilizza un repository, ci sono meno possibilità che tu faccia qualcosa con rebase
che sia disastroso. Potresti ancora rebase
nella direzione sbagliata, ad esempio, e rebase
il tuo ramo principale sul ramo della new-feature
. Per riavere il tuo ramo master
, dovresti eseguire nuovamente il rebase
, questa volta dal ramo della new-feature
al ramo master
. Ciò ripristinerebbe il tuo ramo master
, anche se con una storia dall'aspetto strano.
Non utilizzare rebase
su rami condivisi in cui è probabile che altri funzionino. Le tue modifiche al tuo repository causeranno problemi a molte persone quando invii il tuo codice ribasato al tuo repository remoto.
Se il tuo progetto ha più contributori, la cosa sicura da fare è utilizzare solo rebase
sul tuo repository locale e non su rami pubblici. Allo stesso modo, se le richieste pull fanno parte delle revisioni del codice, non utilizzare rebase
. O almeno, non utilizzare rebase
dopo aver creato la richiesta pull. È probabile che altri sviluppatori guardino i tuoi commit, il che significa che tali modifiche si trovano su un ramo pubblico, anche se non si trovano sul ramo master
.
Il pericolo è che stai per rebase
i commit che sono già stati inviati a un repository remoto e altri sviluppatori potrebbero aver già basato il lavoro su quei commit. Il tuo rebase
locale farà svanire quei commit esistenti. Se invii tali modifiche al repository, non diventerai popolare.
Altri contributori dovranno passare attraverso merge
disordinata per riportare il loro lavoro nel repository. Se poi riporti le loro modifiche al tuo repository locale, ti troverai di fronte alla rimozione di un pasticcio di modifiche duplicate.
Ribasare o non ribasare?
Rebase
potrebbe essere fuorilegge nel tuo progetto. Potrebbero esserci obiezioni locali e culturali. Alcuni progetti o organizzazioni considerano il rebase
come una forma di eresia e un atto di profanazione. Alcune persone credono che la storia di Git dovrebbe essere una registrazione inviolabile e permanente di ciò che è accaduto. Quindi, rebase
potrebbe essere fuori dal tavolo.
Ma, utilizzato localmente, su filiali private, rebase
è uno strumento utile.
Invia dopo aver ribasato e limitalo ai rami in cui sei l'unico sviluppatore. O almeno, dove tutto lo sviluppo si è fermato e nessun altro ha basato nessun altro lavoro sui commit del tuo ramo.
Fallo ed eviterai qualsiasi problema.
CORRELATO: Come controllare e aggiornare la tua versione di Git