Beginner’s Guide to Interactive Rebasing
@StrideStride
Information Technology and Services
All’inizio di quest’anno ho fatto un rebase interattivo per la prima volta e sono rimasto colpito da quello che si può fare con esso. L’ho anche trovato un po’ complesso all’inizio. Speriamo che questa guida aiuti a rimuovere qualche incertezza al riguardo.
Inoltre, poiché è così potente e si può essenzialmente riscrivere la storia, un piccolo avvertimento prima di iniziare: Ci sono molte scuole di pensiero su Git e se il rebasing sia una buona idea o meno. Questo post non si immergerà in queste discussioni ed è puramente inteso a camminare attraverso le basi dell’uso del rebasing interattivo.
TL;DR
- Il rebasing interattivo può essere usato per cambiare i commit in molti modi come la modifica, la cancellazione e lo squash.
- Per dire a Git dove iniziare il rebase interattivo, usa lo SHA-1 o l’indice del commit che precede immediatamente il commit che vuoi modificare.
- Durante un rebase interattivo, quando Git si ferma ad un commit che hai taggato per modificare, il flusso di lavoro non è diverso da un normale processo di commit – metti in scena i file e poi fai il commit. L’unica differenza è che usi il comando
git commit --amend
piuttosto chegit commit
. - Il rebase interattivo creerà nuovi SHA-1 quindi è meglio usare il rebase interattivo sui commit che non hai spinto su un ramo remoto.
Il problema
In questo esempio, lavoreremo su una situazione in cui abbiamo lavorato in un ramo di funzionalità e abbiamo un paio di commit che vorremmo cambiare o cancellare. Ecco come appare il nostro git log:
Dal git log sopra, ecco i due commit che vogliamo cambiare: 4a4d705
– In questo commit abbiamo accidentalmente commesso un conflitto di fusione6c01350
– In questo commit abbiamo rimosso il conflitto di fusione
Quello che vorremmo fare è tornare indietro nel tempo a 4a4d705
, rimuovere il conflitto di fusione nel commit, poi cancellare 6c01350
poiché il conflitto di fusione è risolto e non abbiamo più bisogno di questo commit. Questo sarà un miglioramento per la nostra storia dei commit per due ragioni:
- Non avremo più commit rotti (conflitti di merge)
- Avremo solo commit significativi, nessun commit relativo alla sola correzione di un mancato conflitto di merge
La soluzione
Questa situazione è un buon candidato per il rebasing interattivo. Scott Chacon, nel suo libro Pro Git, descrive il rebasing interattivo come segue: “A volte la cosa corretta … non può essere modificata al commit non proprio perfetto che corregge, perché quel commit è sepolto profondamente in una serie di patch. Questo è esattamente ciò a cui serve il rebase interattivo: usalo dopo un sacco di , riorganizzando e modificando i commit, e schiacciando più commit in uno.”
Quali commit vogliamo modificare?
Per iniziare un rebase interattivo, dobbiamo dire a Git quali commit vogliamo modificare. Lo facciamo facendo riferimento al commit immediatamente precedente al primo commit che vogliamo modificare. O, detto semplicemente, facciamo riferimento “all’ultimo commit che vogliamo mantenere così com’è”, secondo Scott Chacon.
Guardiamo il nostro esempio per capire meglio. Ci sono due modi per fare riferimento a questo commit:
By SHA-1 – L’ultimo commit che vogliamo mantenere as-is ha un SHA-1 di 528f82e
quindi possiamo passarlo nel nostro comando interattivo rebase.
By Index – L’ultimo commit che vogliamo mantenere as-is ha una posizione di indice di 3 (Git usa un’indicizzazione basata su zero) quindi possiamo passare HEAD~3
al nostro comando di rebase interattivo.
Nota – Se hai solo pochi commit su cui fare il rebase interattivo, usare l’indice è probabilmente più facile per la maggior parte delle persone. Tuttavia, se hai molti commit, usare lo SHA-1 è probabilmente più facile in modo da non dover contare fino in fondo al registro git.
Avvia il rebasing interattivo
In base al nostro esempio, eseguiremo o:
$ git rebase -i 528f82e
Oppure
$ git rebase -i HEAD~3
che apre questa finestra in Vim:
Nota che i commit sono nell’ordine opposto di git log. In git log il commit più recente è in cima. In questa vista, il commit più recente è in basso. Notate anche che i commenti sotto danno un utile elenco dei comandi validi che possiamo usare su ogni commit.
Se non conoscete Vim, cliccate semplicemente su ogni parola pick
che volete modificare e poi premete il tasto <i>
(per la modalità inserimento). Una volta che hai finito di scrivere premi il tasto <esc>
per uscire dalla modalità di inserimento.
Nel nostro esempio, abbiamo cambiato il comando in edit
per il commit che vogliamo modificare e abbiamo cambiato il comando in drop
per il commit che vogliamo cancellare. Poi eseguiamo :wq
per salvare ed uscire dalla finestra Vim.
Modifica il commit
Nel terminale vediamo questo messaggio:
Questo ha senso perché siamo fermi a 4a4d705
. Questo è il commit più vecchio nella serie di commit che vogliamo modificare. Inizieremo con questo commit e ci faremo strada attraverso ogni commit fino al più recente.
Come promemoria, 4a4d705
era il commit con il conflitto di fusione che abbiamo accidentalmente commesso. Quando apriamo il nostro editor vediamo il conflitto di fusione lì:
Quindi sistemiamo il conflitto di fusione nel file ma cosa facciamo ora? Nel dubbio, git status
:
Fico! Questo è effettivamente utile. Vediamo che stiamo attualmente modificando 4a4d705
, e vediamo i prossimi due commit su cui agire dopo questo.
Il resto del messaggio ci sta spiegando un flusso di lavoro familiare. Git ci dice che se vogliamo modificare il commit eseguiamo git commit --amend
. Questo agirà essenzialmente come il nostro tipico git commit
che usiamo in un normale flusso di lavoro. In fondo a questo messaggio vediamo che il nostro file è stato modificato riflettendo le modifiche che abbiamo appena fatto per rimuovere il conflitto di merge. Abbiamo bisogno di mettere in scena il file prima di fare il commit. Questo non è diverso da un normale flusso di lavoro.
Tutto quello che facciamo è git add tempChanger.js
per mettere in scena il file modificato e poi git commit --amend
per impegnare il file messo in scena! Questo aprirà di nuovo una finestra Vim con il messaggio di commit:
Possiamo modificare il messaggio di commit o lasciarlo così com’è. Scegliamo di mantenere il messaggio di commit lo stesso e digitiamo :wq
per salvare e uscire dalla finestra.
Abbiamo modificato il nostro vecchio commit. E adesso? Esegui git status
:
Continua il rebase interattivo
Non abbiamo altro da cambiare nel commit quindi continuiamo!
Eseguiamo git rebase --continue
e vediamo il seguente messaggio:
Woah, abbiamo finito? Ma che dire degli altri due commit? Bene, il prossimo commit su cui agire era 6c01350
. Questo commit è stato segnato per essere cancellato (drop
) quando abbiamo iniziato il rebase interattivo. Git lo ha cancellato automaticamente e si è spostato sul commit successivo, 41aa9d2
. Questo non è mai stato modificato nel rebase interattivo iniziale. Il suo comando di default era pick
che significa che il commit sarà usato. Git ha applicato quel commit e dato che era l’ultimo commit, il rebase interattivo è stato completato.
Nota, se avessimo avuto altri commit da modificare, ci saremmo semplicemente spostati sul commit successivo e avremmo iniziato il processo di modifica proprio come abbiamo fatto sopra. Il ciclo continua fino a quando non ci sono più commit.
Il pulsante di espulsione
E’ da notare che se in qualsiasi punto del nostro rebase interattivo facciamo un casino e non sappiamo come sistemarlo, possiamo sempre interrompere. In qualsiasi momento possiamo eseguire git rebase --abort
nel terminale e il rebase interattivo verrà interrotto senza che le modifiche vengano salvate. Avremmo quindi bisogno di ricominciare il rebase interattivo da capo.
Dopo il rebase interattivo
Il nostro log git ora assomiglia a:
Si noterà che alcune cose sono cambiate da prima di iniziare il rebase interattivo:
- Non abbiamo più il commit
6c01350
con il messaggio commit “Remove merge conflict”. Questo è il commit che abbiamo cancellato nel nostro rebase interattivo. - Il nostro commit che abbiamo modificato,
4a4d705
, ha un diverso SHA-1,2b7443d
. - Il nostro commit più recente dal nostro log git originale,
41aa9d2
, ha anche un nuovo SHA-1,2b95e92
. Questo commit non è stato cambiato ma è stato semplicemente applicato al commit precedente2b7443d
.
Effetti collaterali del rebasing interattivo
Per i due commit più recenti nel nostro log git, poiché hanno nuovi SHA-1, Git li vede come commit completamente nuovi. Questo è anche vero per il nostro ultimo commit, 2b95e92
, dove né il messaggio di commit né i file sono cambiati affatto. Questo porta ad un punto importante con il rebasing interattivo: Se modificate un commit, quel commit e tutti i successivi avranno nuovi SHA-1.
Questo non influenzerà nulla se i commit che avete modificato non sono stati spinti su un ramo remoto. Tuttavia, se hai effettivamente completato un rebase interattivo sui commit che erano già stati spinti su un ramo remoto e poi hai spinto di nuovo il tuo ramo vedrai:
Tecnicamente, potresti aggirare questo usando git push --force
ma questo è molto pericoloso. Se il ramo remoto ha i commit di altre persone ma il tuo ramo locale non ha ancora quei commit, cancellerai effettivamente i loro commit.
Un’altra soluzione è usare git push --force-with-lease
che modificherà solo i tuoi commit ma non quelli degli altri, sebbene anche questo possa essere problematico. Per esempio, se un altro sviluppatore ha già quei commit che hanno ricevuto nuovi SHA-1 nel suo ramo locale, quando tira il ramo remoto, avrà conflitti di fusione con ognuno di questi commit.
Quando usare --force-with-lease
va oltre lo scopo di questo post sul blog, ma sarebbe meglio consultare altri membri del tuo team prima di farlo. Puoi leggere di più su git push --force-with-lease
qui.
Il risultato chiave di questa sezione è che è molto più facile e sicuro usare il rebasing interattivo sui commit che non sono stati ancora inviati ad un ramo remoto.
Scritto da Blake DeBoer. Originariamente pubblicato su Dev.to
Senior, Lead, o Principal developer a NYC? Stride sta assumendo! Vuoi migliorare il tuo team tecnico? Guarda come lo facciamo noi! www.stridenyc.com
Tags
Crea il tuo account gratuito per sbloccare la tua esperienza di lettura personalizzata.
Leave a Reply