git rebase
Questo documento presenta un'analisi approfondita del comando git rebase. Il comando di riassegnazione รจ stato illustrato anche nelle pagine dedicate alla configurazione di un repository e alla riscrittura della cronologia. In questa pagina analizzeremo piรน nei dettagli la configurazione e l'esecuzione di git rebase e i casi d'uso e le insidie piรน comuni del comando di riassegnazione.
La riassegnazione รจ una delle due utility Git specializzate nell'integrazione delle modifiche da un branch all'altro. L'altra utilitร di integrazione delle modifiche รจ git merge. Il merge รจ un record delle modifiche che si muove in avanti. Invece, la riassegnazione include efficaci funzioni di riscrittura della cronologia. Per un confronto dettagliato tra merge e riassegnazione, consulta la nostra guida al confronto tra il merge e la riassegnazione. La riassegnazione prevede 2 modalitร principali: modalitร " manuale" e modalitร "interattiva". Di seguito le analizzeremo in modo piรน dettagliato.
Cos'รจ git rebase?
La riassegnazione รจ il processo di spostamento o di unione di una sequenza di commit in un nuovo commit di base. La riassegnazione รจ molto utile e facilmente visualizzabile nel contesto di un flusso di lavoro di creazione dei branch di funzioni. L'intero processo puรฒ essere visualizzato come segue:
Dal punto di vista dei contenuti, la riassegnazione cambia la base del branch da un commit all'altro facendo sembrare come se il branch fosse stato creato da un commit diverso. Internamente, Git ottiene questo risultato creando nuovi commit e applicandoli alla base specificata. ร molto importante capire che anche se il branch ha lo stesso aspetto, รจ composto da commit completamente nuovi.
Utilizzo
Il motivo principale della riassegnazione รจ quello di mantenere una cronologia del progetto lineare. Ad esempio, considera una situazione in cui il branchย principale รจ avanzato da quando hai iniziato a lavorare su un branch di funzioni. Vuoi applicare gli ultimi aggiornamenti del branchย principale al branch di funzioni, ma vuoi mantenere pulita la cronologia del branch in modo che sembri che tu abbia lavorato sull'ultima versione del branchย principale. Ciรฒ offre il vantaggio di un merge ordinato del branch di funzioni nel branchย principale. Perchรฉ vogliamo mantenere una cronologia "pulita"? I vantaggi di avere una cronologia pulita diventano tangibili quando si eseguono operazioni Git per indagare sull'introduzione di una regressione. Uno scenario piรน reale sarebbe:
1. Viene identificato un bug nel branchย principale. Una funzione ha smesso di funzionare.
2. Uno sviluppatore esamina la cronologia del branch principale usando git log. Grazie alla cronologia "pulita", lo sviluppatore รจ in grado di ragionare rapidamente sulla cronologia del progetto.
3. Lo sviluppatore non รจ in grado di individuare il momento in cui รจ stato introdotto il bug usando git log, quindi esegue un comando git bisect.
4. Dal momento che la cronologia di git รจ pulita, git bisect puรฒ mettere a confronto un set perfezionato di commit durante la ricerca della regressione. Lo sviluppatore trova rapidamente il commit che ha introdotto il bug ed รจ in grado di agire di conseguenza.
Scopri di piรน su git log e git bisect consultando le pagine singole corrispondenti.
Hai due opzioni per integrare la funzione nel branchย principale: eseguire direttamente il merge oppure eseguire prima la riassegnazione e poi il merge. La prima opzione si traduce in un merge a 3 vie e in un commit di merge, mentre la seconda si traduce in un merge con avanzamento rapido e in una cronologia perfettamente lineare. Il diagramma seguente mostra come la riassegnazione sul branchย principale faciliti i merge con avanzamento rapido.
La riassegnazione รจ un modo comune per integrare le modifiche upstream nel repository locale. Il pull delle modifiche upstream con git merge si traduce in un commit di merge superfluo ogni volta che desideri vedere l'avanzamento del progetto. D'altra parte, eseguire la riassegnazione รจ come affermare di voler basare le proprie modifiche su ciรฒ che hanno giร fatto gli altri membri del team.
Non eseguire la riassegnazione della cronologia pubblica
Come abbiamo discusso in precedenza nella sezione sulla riscrittura della cronologia, non dovresti mai eseguire la riassegnazione dei commit una volta che sono stati inviati a un repository pubblico. La riassegnazione sostituirebbe i commit meno recenti con quelli nuovi dando l'impressione che la parte della cronologia correlata a questi ultimi sia svanita improvvisamente.
Confronto tra git rebase standard e git rebase interattivo
Si parla di gitย rebaseย interattivo quandoย gitย rebaseย accettaย un argomento -- i, che sta per "interattivo". Senza argomenti, il comando viene eseguito in modalitร standard. In entrambi i casi, supponiamo di aver creato un branch di funzioni separato.
# Create a feature branch based off of main
git checkout -b feature_branch main
# Edit files
git commit -a -m "Adds new feature"Git rebase in modalitร standard prenderร automaticamente i commit nel branch di lavoro corrente e li applicherร alla base del branch inviato.
git rebase <base>Consente di eseguire la riassegnazione automatica del branch corrente su ๏ผbase๏ผ, che puรฒ essere un qualsiasi tipo di riferimento di commit (ad esempio un ID, un nome di branch, un tag o un riferimento relativo a HEAD).
L'esecuzione di git rebase con il flag -i avvia una sessione di riassegnazione interattiva. Invece di spostare ciecamente tutti i commit nella nuova base, la riassegnazione interattiva ti dร l'opportunitร di modificare i singoli commit durante il processo. Ciรฒ consente di ripulire la cronologia rimuovendo, dividendo e modificando una serie esistente di commit. ร come il comando Git commit --amend, ma con una marcia in piรน.
git rebase --interactive <base>Consente di eseguire la riassegnazione del branch corrente su ๏ผbase๏ผ, ma utilizza una sessione di riassegnazione interattiva. Viene aperto un editor in cui รจ possibile immettere i comandi (descritti di seguito) per ogni commit da riassegnare. Questi comandi determinano il modo in cui i singoli commit verranno trasferiti alla nuova base. Puoi inoltre riordinare l'elenco dei commit per cambiare l'ordine dei commit stessi. Dopo aver specificato i comandi per ogni commit nella riassegnazione, Git inizierร a riprodurre i commit applicando i comandi di riassegnazione. I comandi di modifica della riassegnazione sono i seguenti:
pick 2231360 some old commit
pick ee2adc2 Adds new feature
# Rebase 2cf755d..ee2adc2 onto 2cf755d (9 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commitComandi rebase aggiuntivi
Come descritto nei dettagli nella pagina relativa alla riscrittura della cronologia, la riassegnazione puรฒ essere utilizzata per modificare commit meno recenti e duplicati, file sottoposti a commit e messaggi duplicati. Sebbene queste siano le applicazioni piรน comuni, git rebase dispone inoltre di opzioni di comando aggiuntive che possono essere utili in applicazioni piรน complesse.
git rebase-- dsignifica cheย durante la riproduzione il commit verrร scartato dal blocco di commit combinato finale.git rebase -- pย lascia il commit invariato. Il messaggio o il contenuto del commit non verranno modificati e il commit verrร comunque indicato come commit singolo nella cronologia dei branch.git rebase -- xย durante la riproduzione esegue uno script della shell della riga di comando su ogni commit contrassegnato. Un esempio utile potrebbe essere quello di eseguire la suite di test della base di codice su commit specifici, per facilitare l'individuazione delle regressioni durante una riassegnazione.
Riepilogo
La riassegnazione interattiva dร il controllo completo sull'aspetto della cronologia del progetto. Ciรฒ offre molta libertร agli sviluppatori, poichรฉ consente loro di eseguire il commit di una cronologia "disordinata", mentre sono concentrati sulla scrittura di codice, e di tornare indietro e ripulirla quando portano a termine il lavoro.
La maggior parte degli sviluppatori preferisce utilizzare la riassegnazione interattiva per perfezionare un branch di funzioni prima di eseguirne il merge alla base di codice principale. Questo dร loro l'opportunitร di eseguire lo squash dei commit insignificanti, eliminare quelli obsoleti e assicurarsi che tutto il resto sia in ordine prima di eseguire il commit nella cronologia "ufficiale" del progetto. A tutti gli altri, sembrerร che l'intera funzione sia stata sviluppata in un'unica serie di commit ben pianificati.
Il vero potere della riassegnazione interattiva รจ evidente osservando la cronologia del branchย principale risultante. A tutti gli altri, sembrerร che tu sia uno sviluppatore brillante che ha implementato la nuova funzione al primo colpo utilizzando il numero perfetto di commit. Ecco come la riassegnazione interattiva รจ in grado di mantenere pulita e pertinente la cronologia di un progetto.
Opzioni di configurazione
Ci sono alcune proprietร di riassegnazione che possono essere impostate usando git config. Queste opzioni modificheranno l'aspetto dell'output di git rebase.
rebase.stat: un valore booleano impostato su false per impostazione predefinita. L'opzione attiva o disattiva la visualizzazione del contenuto diffstat visivo che mostra cosa รจ cambiato rispetto all'ultima riassegnazione.rebase.autoSquash:un valore booleano che attiva o disattiva il comportamento--autosquash.rebase.missingCommitsCheck:puรฒ essere impostato su piรน valori che cambiano il comportamento di riassegnazione in caso di commit mancanti.
| Stampa l'output di avviso in modalitร interattiva per avvertire della rimozione dei commit |
| Arresta la riassegnazione e stampa i messaggi di avviso relativi ai commit rimossi |
| Configurato per impostazione predefinita, ignora eventuali avvisi di commit mancanti |
rebase.instructionFormat:una stringa di formatogit logche verrร utilizzata per formattare la visualizzazione della riassegnazione interattiva
Applicazione avanzata di riassegnazione
L'argomento della riga di comando --onto puรฒ essere passato a git rebase. Nella modalitร ย --onto di git rebase, il comando si espande in:
git rebase --onto <newbase> <oldbase>Il comando --onto abilita un modulo o una riassegnazione piรน efficace che consente di inviare riferimenti specifici da usare come punte di una riassegnazione. Supponiamo di avere un repository di esempio con branch come il seguente:
o---o---o---o---o main
\
o---o---o---o---o featureA
\
o---o---o featureBfeatureB si basa su featureA, tuttavia, ci rendiamo conto che featureB non dipende da nessuna delle modifiche in featureA e potrebbe essersi semplicemente distaccato dal branch principale.
git rebase --onto main featureA featureBfeatureA รจ ๏ผoldbase๏ผ. mainย diventa la ๏ผnewbase๏ผ e featureB รจ il riferimento per ciรฒ a cui punterร HEAD di ๏ผnewbase๏ผ. I risultati sono quindi:
o---o---o featureB
/
o---o---o---o---o main
\
o---o---o---o---o featureAConoscere i pericoli della riassegnazione
Un avvertimento da considerare quando si usa git rebase รจ che i conflitti di merge possono diventare piรน frequenti durante un flusso di lavoro di riassegnazione. Ciรฒ si verifica se si dispone di un branch di lunga durata che si รจ allontanato da quello principale. Alla fine, sarร necessario eseguire la riassegnazione sul branch principaleย che in quel momento potrebbe contenere molti nuovi commit con cui le modifiche apportate al branch potrebbero entrare in conflitto. ร possibile risolvere facilmente questo problema eseguendo spesso la riassegnazione del branch su quello principale ed eseguendo commit piรน frequenti. Gli argomenti della riga di comando --continue e --abort possono essere inviati a git rebase per far avanzare o ripristinare la riassegnazione durante la gestione dei conflitti.
Una precisazione piรน importante sulla riassegnazione riguarda i commit persi in seguito alla riscrittura interattiva della cronologia. Se vengono eseguiti la riassegnazione in modalitร interattiva e i sottocomandi come lo squash o il drop, i commit verranno rimossi dal log immediato del branch. A prima vista, potrebbe sembrare che i commit siano stati eliminati definitivamente. Tramite git reflog, รจ possibile ripristinare questi commit e annullare l'intera riassegnazione. Per maggiori informazioni sull'uso di git reflog per trovare i commit persi, consulta la nostra pagina di documentazione di Git reflog.
Il comando git rebase in sรฉ non รจ seriamente pericoloso. I veri casi di pericolo sorgono quando si esegue la riscrittura della cronologia con riassegnazioni interattive e si forza il push dei risultati su un branch remoto condiviso da altri utenti. Questo รจ uno schema da evitare in quanto ha la capacitร di sovrascrivere il lavoro di altri utenti remoti quando eseguono il pull.
Ripristino dalla riassegnazione upstream
Se un altro utente ha eseguito la riassegnazione e forzato il push sul branch in cui stai eseguendo il commit, il comando git pull sovrascriverร tutti i commit che hai basato su quel branch precedente con la punta di cui รจ stato forzato il push. Fortunatamente, tramite git reflog puoi ottenere il log di riferimento del branch remoto, in cui puoi trovare il riferimento risalente a prima della riassegnazione. Potrai quindi eseguire la riassegnazione del branch in base a tale riferimento remoto utilizzando l'opzione --onto, come illustrato in precedenza nella sezione Applicazione avanzata di riassegnazione.
Riepilogo
In questo articolo abbiamo trattato l'utilizzo di git rebase. Abbiamo illustrato casi d'uso di base e avanzati e analizzato esempi piรน avanzati. Alcuni argomenti chiave sono:
Confronto tra git rebase standard e le modalitร interattive
Opzioni di configurazione di git rebase
git rebase --onto
Commit persi di git rebase
Abbiamo esaminato l'utilizzo di git rebase con altri strumenti come git reflog, git fetch e git push. Visita le pagine corrispondenti per ulteriori informazioni.