Riscrittura della cronologia
Git commit --amend e altri metodi per riscrivere la cronologia
Introduzione
In questo tutorial verranno descritti i diversi metodi per riscrivere e modificare la cronologia di Git. Git usa diversi metodi per registrare le modifiche. Esamineremo i punti di forza e di debolezza dei diversi metodi e forniremo esempi di come utilizzarli. Questo tutorial illustra alcuni dei motivi più comuni per sovrascrivere le snapshot sottoposte a commit e mostra come evitare le insidie di tale procedura.
Il compito principale di Git è fare in modo che non ti sfuggano mai le modifiche sottoposte a commit. Ma questo strumento è progettato anche per darti il controllo totale sul flusso di lavoro di sviluppo. È inclusa la possibilità di definire il preciso aspetto della cronologia del progetto; tuttavia, crea anche il potenziale di perdita dei commit. Git fornisce comandi di riscrittura della cronologia con un'esclusione di responsabilità in cui è dichiarato che il loro utilizzo potrebbe comportare la perdita dei contenuti.
Git offre diversi meccanismi per memorizzare la cronologia e salvare le modifiche. Questi meccanismi includono: commit —amend
, git rebase
e git reflog
. Queste opzioni rappresentano efficaci scelte di personalizzazione del flusso di lavoro. Alla fine di questo tutorial avrai familiarità con i comandi che ti permetteranno di ricreare i commit di Git e sarai in grado di evitare le insidie più comuni della riscrittura della cronologia.
materiale correlato
Scheda di riferimento rapido di Git
Scopri la soluzione
Impara a utilizzare Git con Bitbucket Cloud
Modifica dell'ultimo commit: git commit --amend
Il comando git commit --amend
è un modo pratico per modificare il commit più recente. Consente di unire le modifiche preparate per il commit al commit precedente, invece di creare un commit completamente nuovo. Può anche essere usato semplicemente per modificare il messaggio di commit precedente senza modificarne la snapshot. Tuttavia, la correzione non altera solo il commit più recente, ma lo sostituisce completamente, il che significa che il commit corretto sarà una nuova entità con un proprio riferimento. Git lo interpreterà come un commit nuovo, visualizzato con un asterisco (*) nel diagramma sottostante. Vi sono alcuni scenari d'uso comuni per git commit --amend
. Esamineremo gli esempi d'uso nelle sezioni seguenti.
Modificare il messaggio di commit di Git più recente
git commit --amend
Supponiamo che tu abbia appena eseguito il commit e che abbia commesso un errore nel messaggio di log del commit. L'esecuzione di questo comando quando non ci sono elementi preparati per il commit ti consente di modificare il messaggio di commit precedente senza alterarne la snapshot.
Nel corso delle attività di sviluppo quotidiane, è molto frequente che vengano eseguiti commit prematuri. È facile formattare il messaggio di commit nel modo sbagliato o dimenticare di preparare per il commit un file. Il flag --amend
è un modo pratico per correggere questi errori di minore importanza.
git commit --amend -m "an updated commit message"
L'aggiunta dell'opzione -m
consente di inviare un nuovo messaggio dalla riga di comando senza che venga richiesto di aprire un editor.
Modifica dei file sottoposti a commit
L'esempio seguente mostra uno scenario comune dello sviluppo basato su Git. Supponiamo di aver modificato alcuni file di cui vorremmo eseguire il commit in una singola snapshot, ma che poi ci dimentichiamo di aggiungere uno di questi file quando eseguiamo il commit per la prima volta. Per correggere l'errore basta semplicemente preparare l'altro file per il commit e quindi eseguire il commit con il flag --amend
:
# Edit hello.py and main.py
git add hello.py
git commit
# Realize you forgot to add the changes from main.py
git add main.py
git commit --amend --no-edit
Il flag --no-edit
permette di apportare la correzione al commit senza modificare il relativo messaggio. Il commit risultante sostituirà quello incompleto e sembrerà che abbiamo eseguito il commit delle modifiche su hello.py
e main.py
in una singola snapshot.
Non correggere i commit pubblici
I commit corretti sono in realtà commit completamente nuovi e il commit precedente non si troverà più sul branch corrente. Questa procedura ha le stesse conseguenze del ripristino di una snapshot pubblica. Evita di correggere un commit su cui altri sviluppatori hanno basato il loro lavoro. Questa sarebbe infatti una situazione confusionaria per gli sviluppatori da cui è complicato riprendersi.
Riepilogo
Per ricapitolare, git commit --amend
consente di prendere il commit più recente e aggiungervi nuove modifiche preparate per il commit. Puoi aggiungere o rimuovere le modifiche dall'area di staging di Git tramite il comando commit --amend
. Se non ci sono modifiche preparate per il commit, il comando --amend
chiederà comunque di modificare l'ultimo log dei messaggi di commit. Fai attenzione quando usi --amend
sui commit condivisi con altri membri del team. La correzione di un commit condiviso con un altro utente potrebbe rendere necessario risolvere conflitti di merge confusionari e lunghi.
Modifica di commit meno recenti o multipli
Per modificare commit meno recenti o multipli, puoi usare git rebase
per unire una sequenza di commit in un nuovo commit di base. Nella modalità standard, git rebase
permette di riscrivere letteralmente la cronologia, applicando automaticamente i commit nel branch di lavoro corrente alla base del branch inviato. Dal momento che i nuovi commit sostituiranno quelli meno recenti, è importante non usare git rebase
sui commit che sono stati resi pubblici o sembrerà che la cronologia del progetto sia scomparsa.
In questi o in casi simili in cui è importante mantenere ordinata la cronologia del progetto, l'aggiunta dell'opzione -i
a git rebase
consente di eseguire il comando rebase interactive
, che permette di modificare i singoli commit durante la procedura, piuttosto che spostare tutti i commit. Per saperne di più sulla riassegnazione interattiva e sui comandi di riassegnazione aggiuntivi, consulta la pagina su git rebase.
Modifica dei file sottoposti a commit
Durante una riassegnazione, il comando edit o e
metterà in pausa la riassegnazione sul commit specifico permettendoti di apportare ulteriori modifiche con il comando git commit --amend
. Git interromperà la riproduzione e visualizzerà un messaggio:
Stopped at 5d025d1... formatting
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Messaggi multipli
Ogni commit Git regolare ha un messaggio di log in cui è spiegato cosa è avvenuto nel commit. Questi messaggi forniscono informazioni preziose sulla cronologia del progetto. Durante una riassegnazione, è possibile eseguire alcuni comandi sui commit per modificare i messaggi di commit.
Eseguire lo squash dei commit per una cronologia pulita
Il comando s
("squash") è dove è possibile vedere la vera utilità della riassegnazione. Lo squash permette di specificare i commit di cui desideri eseguire il merge nei commit precedenti. Questa procedura consente di avere una cronologia "pulita". Durante la riassegnazione, Git eseguirà il comando rebase specificato per ogni commit. Nel caso dei commit con squash, Git aprirà l'editor di testo configurato e chiederà di unire i messaggi di commit specificati. L'intera procedura può essere visualizzata come segue:
Nota che i commit modificati con un comando rebase hanno un ID diverso da quello dei commit originali. I commit contrassegnati con pick avranno un nuovo ID se i commit precedenti sono stati riscritti.
Le moderne soluzioni di hosting Git, come Bitbucket, offrono ora funzioni di "squashing automatico" al momento del merge. Queste funzioni eseguono automaticamente la riassegnazione e lo squash dei commit di un branch quando si utilizza l'interfaccia utente delle soluzioni ospitate. Per maggiori informazioni, consulta "Squash dei commit durante il merge di un branch Git con Bitbucket".
Riepilogo
Il comando git rebase offre la possibilità di modificare la cronologia e la riassegnazione interattiva consente di farlo senza lasciare alcun disordine. Ciò offre la libertà di commettere e correggere gli errori e perfezionare il lavoro, pur mantenendo una cronologia di progetto pulita e lineare.
La rete di sicurezza: git reflog
I log di riferimento, o" reflog," sono un meccanismo utilizzato da Git per registrare gli aggiornamenti apportati alle punte dei branch e altri riferimenti sui commit. Il log di riferimento consente di tornare ai commit anche se non sono usati come riferimento da nessun branch o tag. Dopo aver riscritto la cronologia, il log di riferimento contiene informazioni sullo stato precedente dei branch e consente, se necessario, di ripristinarlo. Ogni volta che la punta del branch viene aggiornata per un motivo qualsiasi (cambiamento di branch, pull di nuove modifiche, riscrittura della cronologia o semplicemente aggiunta di nuovi commit), verrà aggiunta una nuova voce al log di riferimento. In questa sezione esamineremo il comando git reflog
ed esploreremo alcuni usi comuni.
Utilizzo
git reflog
Visualizza il log di riferimento del repository locale.
git reflog --relative-date
Mostra il log di riferimento con le rispettive informazioni sulla data (ad esempio 2 settimane fa).
Esempio
Per comprendere meglio git reflog
, vediamo un esempio.
0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2
Il log di riferimento sopra mostra un'estrazione dal branch principale al branch 2.2 e viceversa. Da qui, viene eseguito un hard reset su un commit precedente. L'ultima attività è rappresentata in alto con l'etichetta HEAD@{0}
.
Se risulta che si è accidentalmente tornati indietro, nel log di riferimento vi sarà il branch main del commit che punta a (0254ea7)
prima che venissero accidentalmente eliminati 2 commit.
git reset --hard 0254ea7
Tramite git reset, è ora possibile ripristinare il branch main al commit precedente. Ciò rappresenta una rete di sicurezza nel caso di modifiche accidentali della cronologia.
È importante notare che il log di riferimento rappresenta una rete di sicurezza solo se le modifiche sono state effettuate nel repository locale e che tale log tiene traccia solo dei movimenti della punta del branch dei repository. Inoltre, le voci del log di riferimento hanno una data di scadenza, impostata su un intervallo predefinito di 90 giorni.
Per ulteriori informazioni, consulta la nostra pagina su git reflog.
Riepilogo
In questo articolo abbiamo descritto diversi metodi per modificare la cronologia di Git e per annullare le modifiche apportate a Git. Abbiamo esaminato la procedura di riassegnazione di Git. Alcuni dei concetti principali più importanti sono:
- Ci sono molti modi per riscrivere la cronologia con Git.
- Usare
git commit --amend
per modificare l'ultimo messaggio di log. - Usare
git commit --amend
per apportare modifiche al commit più recente. - Usare
git rebase
per unire i commit e modificare la cronologia di un branch. git rebase -i
offre un controllo molto più granulare sulle modifiche della cronologia rispetto al comando git rebase standard.
Scopri di più sui comandi che abbiamo descritto consultando le pagine singole corrispondenti:
Condividi l'articolo
Argomento successivo
Letture consigliate
Aggiungi ai preferiti queste risorse per ricevere informazioni sui tipi di team DevOps e aggiornamenti continui su DevOps in Atlassian.