Close

Scopri come annullare le modifiche in Git usando Bitbucket Cloud

Obiettivo

Scopri come annullare le modifiche sul tuo computer locale e su un repository di Bitbucket Cloud mentre collabori con altre persone.

Brief della missione

Comandi trattati in questo tutorial:

  • git revert, git reset, git log e git status

Ora

40 minuti

Pubblico

Questo tutorial presuppone la familiarità con i seguenti comandi git: git clone, git commit, git pull e git push

Sbagliare è umano. Non tutti i push sono perfetti, quindi questo tutorial ti spiegherà come usare le funzioni git più comuni per annullare una o più modifiche in modo sicuro.

Questo tutorial presuppone familiarità con i seguenti comandi git:

Se non conosci questi comandi, possiamo aiutarti a Imparare a usare Git con Bitbucket Cloud. Poi torna qui per scoprire come annullare le modifiche. Questi comandi git possono essere usati negli ambienti Windows o Unix. In questo tutorial saranno utilizzate le utility della riga di comando Unix per spiegare la navigazione dei file di sistema.


Annullamento delle modifiche sul computer locale


Se la modifica che desideri annullare si trova sul tuo sistema locale e non è stato eseguito il push a un repository remoto, esistono due modi principali per annullarla:

Comando

Definizione

git revert

Definizione

Un comando "undo", ma non una tradizionale operazione di annullamento. Anziché rimuovere il commit, inverte le modifiche nel commit e aggiunge poi un nuovo commit con il contenuto inverso. In questo modo la cronologia di Git non va perduta, il che è fondamentale per garantire l'integrità della cronologia delle tue revisioni e una collaborazione affidabile.

git reset

Definizione

Un comando git versatile per annullare le modifiche. Il comando git reset include una vasta gamma di opzioni, ma in questo tutorial utilizzeremo solo le seguenti modalità di ripristino:

  • --soft: effettua il ripristino del valore HEAD nel commit che selezioni. Funziona sostanzialmente come git checkout, ma non crea uno stato head separato.
  • --mixed: effettua il ripristino del valore HEAD nel commit che selezioni nella cronologia e annulla le modifiche nell'indice.
  • --hard: effettua il ripristino del valore HEAD nel commit che selezioni nella cronologia e annulla le modifiche sia nell'indice che nella tua directory di lavoro. In questo tutorial non testeremo un hard reset.

Per una descrizione dettagliata del funzionamento del comando git reset, leggi Git Tools - Reset Demystified (Strumenti Git - Demistificazione del ripristino) su git-scm.com.

Logo di Bitbucket
Scopri la soluzione

Tutorial avanzati su Git

Logo Git
materiale correlato

Comandi Git

In questo tutorial, imparerai a usare molti altri comandi git che possono esserti utili per l'annullamento delle modifiche. Iniziamo!

Eseguire un fork di un repository


Creiamo innanzitutto un repository unico con tutti i codici sorgente. In questa fase stiamo eseguendo il "fork del repository": si tratta di una procedura git estesa che ha luogo quando si ospita un repository condiviso con un servizio di hosting di terzi come Bitbucket.

1. Inserisci o clicca sul seguente URL: https://bitbucket.org/atlassian/tutorial-documentation-tests/commits/all

2. Clicca sul simbolo + sulla barra laterale di sinistra, quindi seleziona Esegui il fork di questo repository, controlla la finestra di dialogo e clicca su Esegui il fork del repository.

3. Verrai indirizzato alla panoramica del nuovo repository.

4. Clicca sul simbolo + e seleziona Clona questo repository.

5. Clona il repository sul tuo computer.

6. Accedi alla Directory contenente il repository clonato.

Ora che hai un repository pieno di codici e una cronologia esistente sul tuo sistema locale, puoi iniziare ad annullare alcune modifiche.

Trovare le modifiche sul sistema locale


Ovviamente devi saper individuare la modifica che desideri annullare. Puoi fare questo sfogliando l'interfaccia utente di commit su Bitbucket e usando alcune utility della riga di comando che possono individuare una modifica specifica.

git status


Ovviamente devi saper individuare la modifica che desideri annullare. Puoi fare questo sfogliando l'interfaccia utente di commit su Bitbucket e usando alcune utility della riga di comando che possono individuare una modifica specifica.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
nothing to commit, working tree clean

Qui l'output del comando git status mostra che è tutto aggiornato con il branch principale remoto e che non sono presenti modifiche in attesa del commit. Nel prossimo esempio apporteremo alcune modifiche al repository e lo esamineremo nello stato con modifiche in sospeso. Ciò significa che nel sistema locale sono presenti modifiche ai file nel repository che non hai preparato (o indicizzato) per l'aggiunta alla cronologia del progetto.

Per illustrare questo esempio, apri innanzitutto il file myquote2.html. Apporta alcune modifiche ai contenuti di myquote2.html, salva ed esci dal file. Eseguiamo di nuovo il comando git status per esaminare il repository in questo stato.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.
 
Changes not staged for commit:
 (use "git add <file>..." to update what will be committed)
 (use "git checkout -- <file>..." to discard changes in working directory)
 
 Modified: myquote2.html
 
no changes added to commit (use "git add" and/or "git commit -a")
--

Qui l'output mostra che il repository contiene modifiche in sospeso in myquote2.html. Buone notizie! Se la modifica che desideri annullare non è stata ancora aggiunta, come nell'esempio qui sopra, all'area di gestione, puoi modificare il file e procedere. Git inizia a monitorare una modifica solo quando la aggiungi all'area di gestione ed esegui poi il commit nella cronologia del progetto.

Ora "annulliamo" le modifiche che abbiamo apportato a myquote2.html. Poiché si tratta di un esempio molto semplice con modifiche minime, abbiamo a disposizione due metodi per annullare le modifiche. Se eseguiamo git checkout myquote2.html, il repository ripristinerà myquote2.html alla versione del commit precedente. In alternativa, possiamo eseguire il comando git reset --hard, che riconvertirà l'intero repository all'ultimo commit.

Git log


Il comando git log ti consente di elencare la cronologia del progetto, filtrarla e cercare modifiche specifiche. Mentre git status ti consente di esaminare la directory di lavoro e l'area di gestione, git log mostra solo la cronologia del commit.

Puoi trovare lo stesso log della cronologia del commit nell'interfaccia utente di Bitbucket accedendo ai commit di un repository. Puoi trovare i commit del nostro repository demo al seguente indirizzo: https://bitbucket.org/dans9190/tutorial-documentation-tests/commits/all. L'output sarà simile a quello dell'utility della riga di comando git log e può esserti utile per trovare e identificare un commit da annullare.

Nel prossimo esempio puoi vedere diversi elementi nella cronologia, ma di fatto ogni modifica consiste in un commit che dovremo trovare e annullare.

$ git status
On branch main
Your branch is up-to-date with 'origin/main'.

nothing to commit, working tree clean

$ git log

commit 1f08a70e28d84d5034a8076db9103f22ec2e982c
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Wed Feb 7 17:06:50 2018 +0000

    Initial Bitbucket Pipelines configuration

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700

    repeated quote to show how a change moves through the process

commit 4801b87c2147dce83f1bf31acfcffa6cb1d7e0a5
Merge: 1a6a403 3b29606
Author: Dan Stevens [Atlassian] <dstevens@atlassian.com>
Date:   Fri Jul 29 18:45:34 2016 +0000

    Merged in changes (pull request #6)

    Changes

Analizziamo più nel dettaglio uno dei commit nella lista:

commit 52f823ca251a132225dd1cc18ad768de8d336e84
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Fri Sep 30 15:50:58 2016 -0700
 
    repeated quote to show how a change moves through the process

Come puoi notare, ogni messaggio di commit contiene quattro elementi:

Elemento

Descrizione

Hash del commit

Descrizione

Una stringa alfanumerica (codificata con SHA-1) che identifica questa modifica specifica

Autore

Descrizione

La persona che ha eseguito il commit della modifica

Data

Descrizione

La data in cui è stato eseguito il commit della modifica nel progetto

Messaggio di commit

Descrizione

Una stringa di testo che descrive le modifiche.

Suggerimento: scrivi messaggi di commit brevi e descrittivi e contribuirai alla creazione di un repository di lavoro migliore per tutti.

Individuare un commit specifico


Molto probabilmente la modifica che desideri annullare si troverà abbastanza indietro nella cronologia del progetto, che può essere molto ampia. Impariamo quindi alcune operazioni di base che consistono nell'usare il comando git log per trovare una modifica specifica.

1. Accedi alla finestra del tuo terminale e vai al livello superiore del tuo repository locale usando il comando cd (cambia directory).

$ cd ~/repos/tutorial-documentation-tests/

Inserisci il comando git log --oneline. Aggiungendo --oneline, visualizzerai ogni commit su una riga separata e vedrai una porzione maggiore di cronologia nel tuo terminale.

Premi il tasto q per uscire dal log di commit e tornare al tuo prompt dei comandi in qualsiasi momento.

Il prossimo esempio mostra ciò che vedrai:

$ git log --oneline
1f08a70 (HEAD -> main, origin/main, origin/HEAD) Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
...

2. Premi il tasto q per tornare al tuo prompt dei comandi.

3. Individua il commit con l'hash c5826da e altre modifiche nella lista che ha prodotto il comando git log. Qualcuno non ha scritto un messaggio di commit descrittivo, quindi dovremo capire se sono presenti le modifiche di cui abbiamo bisogno.

4. Evidenzia e copia l'hash di commit c5826da dal risultato di git log nella finestra del terminale.

5. Digita git show, quindi incolla o trascrivi l'hash del commit che hai copiato e premi Invio. Dovresti vedere quanto segue:

$git show c5826daeb6ee3fd89e63ce35fc9f3594fe243605
commit c5826daeb6ee3fd89e63ce35fc9f3594fe243605
Author: Daniel Stevens <dstevens@atlassian.com>
Date:   Tue Sep 8 13:50:23 2015 -0700

    more changes

diff --git a/README.md b/README.md
index bdaee88..6bb2629 100644
--- a/README.md
+++ b/README.md
@@ -11,12 +11,7 @@ This README would normally document whatever steps are necessary to get your app
 ### How do I get set up? ###

 * Summary of set up
-* Configuration
-* Dependencies
-* Database configuration
-* How to run tests
-* Deployment instructions
-* more stuff and things
:

La compilazione del prompt in basso proseguirà fino a quando non mostrerà la modifica completa. Premi q per uscire dal tuo prompt dei comandi.

Applicare un filtro a git log per trovare un commit specifico


Questo filtro

Fa questo

Questo comando di esempio

Ha come risultato

-

Fa questo

Limita il numero di commit mostrati

Questo comando di esempio

git log -10

Ha come risultato

I 10 commit più recenti nella cronologia

--after

--before

Fa questo

Limita i commit mostrati all'intervallo di tempo corrispondente

Puoi anche usare
--after "aaaa-mm-gg" --before "aaaa-mm-gg"

Questo comando di esempio

git log --after 2017-07-04

Ha come risultato

Tutti i commit dopo il 4 luglio 2017

--author="nome"

Fa questo

Elenca tutti i commit il cui autore corrisponde al nome

Questo comando di esempio

git log --author="Alana"

Ha come risultato

Tutti i commit eseguiti da qualsiasi autore con Alana nel campo del nome

--grep="stringa del messaggio"

Fa questo

Riporta tutti i commit con un messaggio di commit che corrisponde alla stringa che hai inserito

Questo comando di esempio

git log --grep="HOT-"

Ha come risultato

Tutti i commit che contengono la stringa di testo HOT- nel messaggio

Ti abbiamo presentato una breve panoramica del comando git log. Se ti interessa, dai un'occhiata anche al tutorial avanzato sul comando git log.

Annullare una modifica con git reset


Per iniziare, annulliamo l'ultimo commit nella cronologia. In questo caso, supponiamo che tu abbia appena abilitato le pipelines CI/CD di Bitbucket ma hai capito che lo script non è del tutto corretto.

1. Inserisci git log --oneline nella finestra del tuo terminale.

2. Copia l'hash del commit per il secondo commit nel log: 52f823c, quindi premi q per uscire dal log.

3. Inserisci git reset --soft 52f823c nella finestra del tuo terminale. Il comando dovrebbe essere eseguito in background se ha esito positivo. Ecco fatto! Hai apportato la tua prima modifica. Ora vediamo il risultato di questa azione.

4. Inserisci git status nella finestra del tuo terminale e vedrai che il commit è stato annullato ed è diventato una modifica senza commit. Dovrebbe avere il seguente aspetto:

$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
 
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
 
    new file:   bitbucket-pipelines.yml

5. Inserisci git log --oneline nella finestra del tuo terminale. Dovresti vedere quanto segue:

$ git log --oneline
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 (origin/changes) myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes

6. Noterai che il nuovo valore HEAD del branch è il commit 52f823c, che è esattamente ciò che volevi.

7. Premi q per uscire dal log. Lascia aperto il tuo terminale perché, ora che sai eseguire un semplice ripristino, proveremo a fare qualcosa di un po' più complesso.

Annullare più modifiche con git reset


Per iniziare, annulliamo l'ultimo commit nella cronologia. In questo caso, supponiamo che tu abbia appena abilitato le pipelines CI/CD di Bitbucket ma hai capito che lo script non è del tutto corretto.

1. Inserisci git log --online

2. Copia l'hash del commit 1a6a403 (modificato in myquote online con Bitbucket), che corrisponde al commit nella richiesta di pull #6 contenente le modifiche che desideriamo annullare.

3. Inserisci git reset 1a6a403 nella finestra del tuo terminale. L'output dovrebbe avere il seguente aspetto:

$ git reset 1a6a403
Unstaged changes after reset:
M README.md
M myquote2.html

Noterai che ora le modifiche sono in uno stato "senza commit". Ciò significa che abbiamo rimosso diverse modifiche sia dalla cronologia del progetto che dall'area di gestione.

4. Inserisci git status nella finestra del tuo terminale. L'output dovrebbe avere il seguente aspetto:

$ git status
On branch main
Your branch is behind 'origin/main' by 6 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
 
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
    modified:   README.md
    modified:   myquote2.html
 
Untracked files:
  (use "git add <file>..." to include in what will be committed)
 
    bitbucket-pipelines.yml
 
no changes added to commit (use "git add" and/or "git commit -a")

Ora puoi vedere che la prima modifica che abbiamo annullato (il file bitbucket-pipelines.yml) non è tracciata da git. Questo perché git reset rimuove la modifica sia dalla testa del branch che dall'area di monitoraggio o dell'indice di git. Il processo alla base è più complesso di quanto sembri. Puoi approfondire questo argomento in git reset.

5. Inserisci git log --oneline nella finestra del tuo terminale.

1a6a403 myquote edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
879f965 adding to the quote file
8994332 Merged in HOT-235 (pull request #2)
b4a0b43 removed sarcastic remarks because they violate policy.
b5f5199 myquote2.html created online with Bitbucket
b851618 adding my first file
5b43509 writing and using tests

Ora l'output del log mostra che è stata modificata anche la cronologia del commit e inizia con il commit 1a6a403. A titolo esemplificativo, supponiamo ora di voler annullare il ripristino che abbiamo appena eseguito. Dopo ulteriori considerazioni, forse preferiamo mantenere i contenuti della richiesta di pull #6.

Eseguire il push delle reimpostazioni a Bitbucket


Il comando git reset costituisce uno dei pochi metodi "annulla" offerti da Git. In genere il ripristino viene considerato un'opzione "non sicura" per annullare le modifiche. Va bene quando si lavora localmente su un codice isolato ma diventa rischioso quando lo condivi con i membri del team.

Per condividere un branch che è stato ripristinato con un team in remoto, è necessario eseguire un "push forzato". Puoi avviare un "push forzato" eseguendo git push -f. Un push forzato distruggerà qualsiasi cronologia sul branch successiva all'ultimo push.

Segue un esempio di questo scenario "non sicuro":

  • Lo sviluppatore A sta lavorando su un branch per sviluppare una nuova funzione.
  • Lo sviluppatore B sta lavorando sullo stesso branch per sviluppare un'altra funzione.
  • Lo sviluppatore B decide di ripristinare il branch a uno stato precedente al momento in cui gli sviluppatori A e B hanno iniziato a lavorare.
  • Lo sviluppatore B esegue quindi il push forzato per ripristinare il branch al repository remoto.
  • Lo sviluppatore A esegue il pull del branch per ricevere eventuali aggiornamenti. Durante questa fase, lo sviluppatore A riceve l'aggiornamento forzato. Questo ripristina il branch locale dello sviluppatore A a una versione precedente e i commit vanno perduti.

Annullare un comando git reset


Finora abbiamo passato gli hash SHA dei git commit ai git reset. Ora l'output di git log non contiene i commit che abbiamo ripristinato. Come possiamo recuperarli? Git non elimina mai completamente un commit a meno che non sia stato rimosso anche il puntatore. Inoltre Git memorizza un log separato di tutte le operazioni, definito "reflog". Possiamo esaminare il reflog eseguendo il comando git reflog.

1a6a403 HEAD@{0}: reset: moving to 1a6a403
1f08a70 HEAD@{1}: reset: moving to origin/main
1f08a70 HEAD@{2}: clone: from git@bitbucket.org:dans9190/tutorial-documentation-tests.git

L'output di git reflog dovrebbe essere simile a quello mostrato sopra. Puoi vedere la cronologia delle azioni nel repository. La riga in alto è un riferimento all'operazione che abbiamo eseguito per reimpostare la pull request n.6. Ora eseguiamo un'ulteriore operazione di reimpostazione della pull request n.6. La seconda colonna dell'output di questo reflog indica un puntatore di riferimento a un'azione di modifica eseguita sul repository. Qui HEAD@{{0}} è un riferimento al comando di reimpostazione eseguito in precedenza. Non vogliamo ripetere tale comando di reimpostazione, quindi reimposteremo il repository su HEAD@{{1}}.

$ git reset --hard HEAD@{1}
HEAD is now at 1f08a70 Initial Bitbucket Pipelines configuration

Esaminiamo ora la cronologia dei commit dei repository con git log --oneline:

$git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Ora l'output del log mostra che è stata modificata anche la cronologia del commit e inizia con il commit 1a6a403. A titolo esemplificativo, supponiamo ora di voler annullare il ripristino che abbiamo appena eseguito. Dopo ulteriori considerazioni, forse preferiamo mantenere i contenuti della richiesta di pull #6.

git revert


Gli esempi precedenti hanno illustrato alcune operazioni di annullamento usando git reset e git reflog. Git contiene un'altra utility "annulla" che viene spesso considerata "più sicura" rispetto al ripristino. L'inversione crea nuovi commit che invertono le modifiche apportate ai commit specificati. È possibile eseguire in modo sicuro il push di questi commit di inversione in repository remoti per poterli condividere con altri sviluppatori.

La seguente sezione mostrerà l'uso del comando git revert. Continuiamo con l'esempio della sezione precedente. Per iniziare, esaminiamo il log e troviamo un commit da invertire.

$ git log --online
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
1f08a70 Initial Bitbucket Pipelines configuration
52f823c repeated quote to show how a change moves through the process
4801b87 Merged in changes (pull request #6)
1a6a403 myquote edited online with Bitbucket
3b29606 myquote2.html edited online with Bitbucket
8b236d9 myquote edited online with Bitbucket
235b9a7 testing prs
c5826da more changes
43a87f4 remivng
d5c4c62 a few small changes
23a7476 Merged in new-feature2 (pull request #3)
5cc4e1e add a commit message
cbbb5d6 trying a thing
438f956 adding section for permissions and cleaning up some formatting
23251c1 updated snipptes.xml organization into resources. other files misc changes
3f630f8 Adding file to track changes
e52470d README.md edited online with Bitbucket
e2fad94 README.md edited online with Bitbucket
592f84f Merge branch 'main' into new-feature2 Merge branch  especially if it merges an updated upstream into a topic branch.
7d0bab8 added a line
:

Per questo esempio selezioniamo il commit 1f08a70 più recente come commit su cui operare. In questo caso, supponiamo di voler annullare le modifiche apportate nel commit. Esegui:

$ git revert 1f08a70

Avvierai un flusso di lavoro git merge. Git creerà un nuovo commit il cui contenuto consiste in un'inversione del commit specificato per l'inversione. Git aprirà quindi un editor di testo configurato per eseguire un nuovo messaggio di commit. L'inversione è considerata l'opzione di annullamento più sicura a causa di questo flusso di lavoro di commit. La creazione di commit di inversione lascia una traccia evidente nella cronologia dei commit, che testimonia il momento in cui è stata eseguita l'operazione di annullamento.

Hai appena imparato ad annullare le modifiche!


Congratulazioni, hai completato il tutorial. Torna qui in qualsiasi momento o vai alla sezione Annullamento delle modifiche per approfondire questo argomento. Continua così!


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