Annullare le modifiche in Git: Spiegazione di Reset, Restore e Revert

Hai dubbi su `git reset`, `git restore` e `git revert`? Questa guida ne chiarisce le differenze e fornisce esempi pratici. Impara come eliminare in sicurezza le modifiche, rimuovere i file dall'area di staging e riscrivere o annullare in sicurezza i commit nella tua cronologia Git. Padroneggia questi comandi essenziali per un controllo della versione efficace e una timeline del progetto più pulita.

48 visualizzazioni

Annullare le modifiche in Git: Reset, Restore, Revert Spiegati

Git è un potente sistema di controllo versione che ti permette di tenere traccia delle modifiche alla tua codebase. Tuttavia, gli errori accadono e potresti aver bisogno di annullare delle modifiche. Git fornisce diversi comandi per aiutarti in questo, ma funzionano in modi molto diversi e influenzano il tuo repository in modi distinti. Comprendere le sfumature tra git reset, git restore e git revert è cruciale per gestire efficacemente la cronologia del tuo progetto e correggere gli errori senza conseguenze indesiderate.

Questo articolo demistificherà questi tre comandi, spiegando il loro scopo, come funzionano e quando usarli. Sfrutteremo la documentazione ufficiale di Git e i modelli di utilizzo comuni per fornire spiegazioni chiare ed esempi pratici. Alla fine di questa guida, sarai in grado di annullare le modifiche con sicurezza, gestire i tuoi file in staging e mantenere una cronologia dei commit pulita e coerente.

Comprendere i concetti chiave

Prima di immergerti nei comandi, è importante afferrare alcuni concetti di Git:

  • Working Directory (Cartella di Lavoro): I file che stai attualmente modificando.
  • Staging Area (Index): Un'area di sosta dove prepari le modifiche prima di effettuarne il commit. git add sposta le modifiche dalla working directory alla staging area.
  • Commit History (Cronologia dei Commit): Una sequenza di snapshot del tuo progetto nel tempo, rappresentata dai commit.
  • HEAD: Un puntatore all'ultimo commit sulla tua branch corrente.

Questi tre comandi interagiscono principalmente con queste aree per modificare o scartare le modifiche.

git restore: Per scartare le modifiche nella Working Directory e nella Staging Area

Il comando git restore, introdotto più recentemente in Git, è progettato per il compito semplice di annullare le modifiche nella tua working directory o di de-stagiare i file. È generalmente considerato più sicuro e più intuitivo per queste operazioni specifiche rispetto a git reset.

De-stagiare i file

Se hai accidentalmente messo in staging un file usando git add e vuoi de-stagiarlo, git restore è il comando da usare. Sposta le modifiche dalla staging area alla tua working directory, ma non scarta le modifiche stesse.

  • De-stagia un file specifico:
    bash git restore <file>
    Questo comando prende la versione del file dall'indice (staging area) e la rimette nell'indice. In sostanza, rimuove il file dallo staging per il prossimo commit, ma le modifiche rimangono nella tua working directory.

  • De-stagia tutti i file:
    Sebbene non esista un git restore . diretto per de-stagiare tutto come può fare git reset, di solito applicheresti git restore a singoli file o lo useresti in combinazione con altri comandi se necessario. Tuttavia, il caso d'uso più comune è de-stagiare file specifici.

Scartare le modifiche nella Working Directory

git restore può anche essere usato per scartare tutte le modifiche non in staging nella tua working directory per un file specifico, riportandolo alla versione nella staging area (index) o all'ultimo stato committato.

  • Scarta le modifiche non in staging in un file:
    bash git restore <file>
    (Nota: Questo comando può avere due significati a seconda del contesto. Se usato senza --staged, si rivolge principalmente alla working tree. Se il file è in staging, lo de-stagia. Se il file è modificato nella working tree e non in staging, ripristina il file della working tree per farlo corrispondere all'indice.)

  • Scarta sia le modifiche in staging che quelle non in staging per un file (ripristina a HEAD):
    Per scartare completamente tutte le modifiche (sia in staging che non in staging) per un file e riportarlo allo stato in cui si trovava al commit HEAD:
    bash git restore --staged --worktree <file>
    Questo è un comando potente che reimposta efficacemente il file al suo ultimo stato committato.

Ripristinare un file da un commit specifico

git restore può anche recuperare la versione di un file specifico da un commit passato senza alterare la cronologia del tuo branch.

git restore <file> --source <commit>

Sostituisci <commit> con l'hash del commit o un riferimento simbolico come HEAD~1.

git reset: Riscrivere la Cronologia

git reset è un comando più potente che può modificare la cronologia dei tuoi commit spostando il puntatore HEAD del branch corrente. Può anche influenzare l'area di staging e la working directory, a seconda della modalità utilizzata.

Comprendere le Modalità (--soft, --mixed, --hard)

git reset ha tre modalità principali:

  1. --soft: Sposta HEAD al commit specificato ma lascia la tua staging area e working directory intatte. Le modifiche dai commit resettati appaiono come modifiche in staging.
    bash git reset --soft HEAD^ # Sposta HEAD indietro di un commit, le modifiche dal commit annullato sono in staging

  2. --mixed (predefinito): Sposta HEAD e resetta la staging area per farla corrispondere al commit specificato. Le modifiche dai commit resettati sono presenti nella tua working directory ma non sono in staging.
    bash git reset HEAD^ # Equivalente a git reset --mixed HEAD^ # Sposta HEAD indietro di un commit, le modifiche dal commit annullato non sono in staging

  3. --hard: Sposta HEAD e resetta sia la staging area che la working directory per farle corrispondere al commit specificato. Questo scarta tutte le modifiche dai commit che vengono resettati e qualsiasi modifica non committata successiva nella working directory. Usare con estrema cautela.
    bash git reset --hard HEAD~ # Scarta l'ultimo commit E tutte le modifiche successive nella working directory e nella staging area

Casi d'uso per git reset:

  • De-stagiare i file: git reset <file> è una scorciatoia per git restore --staged <file>, che rimuove un file dalla staging area senza influenzare la working directory.
  • De-stagiare tutto: git reset (senza argomenti o specificando HEAD) de-stagia tutte le modifiche attualmente in staging, spostandole di nuovo nella working directory (equivalente a git restore --staged .).
  • Annullare l'ultimo commit: git reset HEAD^ (o git reset --soft HEAD^) è comunemente usato per modificare l'ultimo commit. Le modifiche del commit precedente sono ora in staging, pronte per essere committate nuovamente con modifiche o un nuovo messaggio.
  • Scartare tutte le modifiche locali: git reset --hard è usato per scartare completamente tutte le modifiche locali (in staging e non in staging) e riportare il repository a un commit specifico. Questa è un'operazione distruttiva.

Resettare un vecchio commit

Se hai bisogno di annullare le modifiche da un commit che non è il più recente, puoi usare git reset. Ad esempio, per resettare a un commit prima di uno problematico:

# Esempio: Annulla gli ultimi 2 commit, mantenendo le modifiche non in staging
git reset --mixed HEAD~2

Avvertenza: git reset riscrive la cronologia. Se hai già effettuato il push dei commit che stai resettando, ciò può causare problemi significativi ai collaboratori. È generalmente sicuro resettare i commit che esistono solo nel tuo repository locale.

git revert: Creare un nuovo commit per annullare le modifiche

git revert è il modo più sicuro per annullare le modifiche in una cronologia condivisa o pubblicata. Invece di riscrivere la cronologia, crea un nuovo commit che introduce le modifiche inverse di un commit precedente.

Come funziona

Quando esegui git revert <commit>, Git analizza il commit specificato, calcola le modifiche opposte e le applica alla tua working directory e staging area correnti. Ti chiede quindi di creare un nuovo commit con un messaggio predefinito che indica quale commit è stato annullato.

  • Annulla un commit specifico:
    bash git revert <commit-hash>
    Questo creerà un nuovo commit che annulla le modifiche introdotte da <commit-hash>. Se ci sono conflitti di merge, Git si metterà in pausa e richiederà di risolverli prima di committare.

  • Annullare più commit:
    Puoi annullare un intervallo di commit:
    bash # Annulla i commit da HEAD~3 fino a (ma non includendo) HEAD git revert HEAD~3..HEAD
    Git tenterà di creare un commit di annullamento per ogni commit specificato. Se sorgono conflitti durante il processo, dovrai risolverli per ogni annullamento.

Vantaggi di git revert:

  • Preserva la cronologia: Non altera i commit esistenti, rendendolo sicuro per branch pubblici o condivisi.
  • Traccia di audit chiara: Il commit di annullamento dichiara esplicitamente cosa è stato annullato e perché.
  • Gestisce i merge con grazia: Git può spesso annullare automaticamente i merge commit, sebbene possa essere necessario un intervento manuale per scenari complessi.

Quando usare git revert:

  • Quando è necessario annullare le modifiche su un branch che è già stato pushato a un repository remoto.
  • Quando si desidera mantenere un registro chiaro e immutabile di tutte le modifiche, incluse le correzioni.
  • Quando si annulla un merge commit.

Scegliere il comando giusto

Ecco una semplice guida per aiutarti a decidere:

  • Per de-stagiare un file: Usa git restore <file> o git reset <file>.
  • Per scartare le modifiche non in staging nella tua working directory per un file: Usa git restore <file>.
  • Per scartare tutte le modifiche (in staging e non in staging) per un file: Usa git restore --staged --worktree <file>.
  • Per annullare l'ultimo commit e mantenere le modifiche in staging (per una modifica): Usa git reset --soft HEAD^.
  • Per annullare l'ultimo commit e mantenere le modifiche non in staging: Usa git reset HEAD^.
  • Per scartare completamente l'ultimo commit e tutte le modifiche successive (distruttivo): Usa git reset --hard HEAD^.
  • Per annullare un commit su un branch condiviso senza riscrivere la cronologia: Usa git revert <commit-hash>.
  • Per scartare tutte le modifiche locali nell'intero repository (distruttivo): Usa git reset --hard.

Conclusione

Padroneggiare git reset, git restore e git revert è fondamentale per un uso efficace di Git. git restore è la tua scelta principale per scartare in sicurezza le modifiche nella working directory e nella staging area. git reset offre potenti capacità di riscrittura della cronologia, meglio utilizzate su commit locali, non pushati. git revert fornisce un metodo sicuro e che preserva la cronologia per annullare le modifiche, specialmente cruciale negli ambienti collaborativi. Comprendendo i loro comportamenti distinti e scegliendo il comando appropriato, puoi gestire con sicurezza l'evoluzione del tuo progetto e correggere eventuali errori lungo il percorso.