Rimozione del Commit di Fusione con Git: Una Guida con Esempi

Possiamo compromettere un’applicazione fondendo del codice problematico, sia a causa dell’integrazione accidentale di lavoro incompiuto nel ramo principale o per non aver rilevato un bug critico che è sfuggito ai test automatici.

În questo articolo, ti guiderò attraverso il processo di utilizzo di git revert per annullare in sicurezza una fusione, garantendo che la cronologia dei commit rimanga intatta e l’integrità del progetto sia preservata.

Wie git revert Funziona

Possiamo pensare a git revert come alla versione di Git del comando annulla. Tuttavia, il comando git revert non elimina i commit o salta a uno stato precedente del ramo. Invece, crea un nuovo commit che ripristina le modifiche da un commit specifico.

La sintassi per revertire un commit con hash <commit_hash> è:

git revert <commit_hash>

Possiamo elencare i commit insieme ai loro identificatori hash utilizzando il comando git log. L’output del git log elenca i commit dal più recente al più vecchio, come segue:

Per esempio, per revertire il commit che implements la funzione di sottrazione, useremmo il comando:

git revert 7ba24a3e62d4d37182428ccfaa070baa222b1151

Utilizzando git revert possiamo annullare le modifiche di un commit specifico senza influenzare la cronologia dei commit.

Attenzione che git revert non è magico e a seconda della cronologia dei commit, può portare a un conflitto che deve essere risolto manualmente.

Vantaggi di git revert rispetto alle modifiche manuali

Perché git revert è utile se dobbiamo risolvere un conflitto manualmente? Non sarebbe più facile annullare le modifiche manualmente? Vediamo i suoi vantaggi:

  • Preserva la storia: git revert crea un nuovo commit che annulla le modifiche di un commit specifico mentre preserved l’intera cronologia dei commit. Questo aiuta a mantenere una cronologia trasparente delle modifiche e delle reversali.
  • Reversale atomica: garantisce che le reversali siano atomiche e coerenti. Quando cancelliamo e commitiamo le modifiche manualmente, c’è un rischio di errore umano.
  • Consapevolezza dei conflitti: assicura che siamo avvisati attraverso i conflitti se ci sono integrazioni o modifiche dipendenti dal commit originale. Questo potrebbe sembrare scomodo, ma protegge contro effetti collaterali indesiderati.
  • Metadati: il nuovo commit creato da git revert include metadati e un messaggio di commit che descrive contestualmente cosa è stato revertito, aiutando a comprendere in futuro. Senza git revert, questo contesto potrebbe essere perso.

Revertire una Fusione in Diversi Scenari

In questa sezione, impariamo come annullare una fusione. Per esempio, stiamo assumendo che stiamo fondendo un ramo chiamato feature nel ramo main eseguendo il comando dal ramo main:

git merge feature

Quello che impariamo qui può essere applicato a qualsiasi coppia di rami sostituendo i nomi di conseguenza.

Annullare una fusione che non ha commit associati

Il comando git merge non sempre crea un nuovo commit. Un commit viene creato solo se il ramo main si è discostato dal ramo feature. Poiché git revert richiede un commit per operare, non possiamo usarlo in questo caso.

I rami main e feature si discostano quando vengono creati nuovi commit su main che non sono antenati del ramo feature. In altre parole, sono stati creati nuovi commit su main dopo che è stato creato il feature.

Se i rami non si sono discostati, quando eseguiamo il comando git merge feature sul ramo principale, Git utilizzerà il fast-forward per fare la fusione. Questo significa che sposta il HEAD del ramo main al HEAD del ramo feature.

Possiamo osservare che questo è successo guardando il risultato di git merge:

Per annullare tale fusione, dobbiamo solo riportare il HEAD del ramo main al suo precedente stato. Per questo, ci:

  1. Identifichiamo il precedente HEAD utilizzando il git reflog
  2. Reimposta il HEAD al precedente utilizzando git reset --hard <previous_head>, sostituendo <previous_head> con il precedente HEAD.

L’output di git reflog apparirà qualcosa del genere:

Possiamo identificare il precedente HEAD guardando la riga che dice “checkout: moving from feature to main” (scrive feature e main perché questi sono i nomi delle nostre branch). 

In questo caso, il precedente head è fe59838. Per spostare il HEAD della branch main indietro a questo e annullare il merge, utilizziamo quindi il comando:

git reset --hard fe59838

Revertire un merge che ha un commit associato

Se la branch main e la branch feature si sono divise, allora quando uniamo le due branch, viene creato un nuovo commit, chiamato commit di merge. 

Il commit di merge applica le modifiche da una branch all’altra. In questo caso, le modifiche in feature vengono applicate alla branch main.

Per revertire le modifiche sulla branch main, utilizziamo il comando git revert sul commit di merge. Questo creerà un nuovo commit che annulla le modifiche portate nella branch main con il merge, ripristinando effettivamente lo stato della branch main a quello che era prima del merge.

Prima, dobbiamo identificare l’hash del commit di fusione. Possiamo farlo utilizzando il comando git log:

Poiché il commit di fusione ha due genitori, la sintassi di git revert è leggermente diversa. Dobbiamo utilizzare l’opzione -m 1 per specificare che vogliamo revert le modifiche relative al ramo main:

git revert -m 1 b8dab2c8611e324ed0d273133987415350e6d10d

Risoluzione dei Conflitti Quando si Revert un Commit

A volte, possono sorgere conflitti quando si revert un commit, specialmente se il commit da revert è in conflitto con modifiche successive nel codice. In tali casi:

  1. Git metterà in pausa il revert: Dobbiamo risolvere manualmente i conflitti. Git marcherà i file in conflitto e richiederà intervento.
  2. Risolvere i conflitti: Apriamo ogni file in conflitto, risolviamo i conflitti contrassegnati da Git e salviamo le modifiche.
  3. Aggiungere i file risolti: git add <percorso-file>
  4. Continuare il revert: git revert --continue

Conclusione

Utilizzare git revert per annullare i commit di fusione garantisce che ogni cambiamento e correzione sia documentato all’interno della cronologia dei commit.

Inoltre, comprendere gli scenari appropriati per utilizzare git reset rispetto a git revert ci permette di prendere decisioni migliori, specialmente quando si considerano flussi di lavoro collaborativi o modifiche locali.

Puoi leggere di più su questo argomento nella sezione FAQ qui sotto. Se vuoi approfondire Git, ti consiglio queste risorse:

Source:
https://www.datacamp.com/tutorial/git-revert-merge