Close

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.

Logo Git
materiale correlato

Scheda di riferimento rapido di Git

Logo di Bitbucket
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.

Git commit amend

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:

Tutorial su Git: esempio di git rebase -i

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.

Le persone collaborano utilizzando una parete piena di strumenti

Blog di Bitbucket

Illustrazione su Devops

Percorso di apprendimento DevOps

Funzione Demo Den per demo con esperti Atlassian

Come Bitbucket Cloud funziona con Atlassian Open DevOps

Iscriviti alla nostra newsletter DevOps

Thank you for signing up