Salta el contingut
 

Revert

Joan Puigcerver Ibáñez

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Revertir un commit (git revert)

L'ordre git revert permet desfer els canvis d'un commit concret sense alterar la història del repositori. Per fer-ho, crea un commit nou que inverteix els canvis del commit que es vol desfer.

A diferència de git reset, no elimina cap commit, de manera que es pot utilitzar sense problemes en branques que ja s'han publicat en un repositori remot.

La sintaxi és la següent:

git revert <ref>
  • <ref>: referència del commit que es vol desfer.

Documentació oficial: git revert – Git

Funcionament de git revert Funcionament de git revert

Figura 1. Funcionament de git revert.

Preparació del repositori

El repositori dels exemples es prepara amb les ordres següents:

setup_revert.sh
#!/bin/bash

# Elimina el repositori si existeix
if [ -d ~/git_revert ]; then
    rm -rf ~/git_revert
fi

mkdir -p ~/git_revert
cd ~/git_revert
git init
git branch -m main
echo "# Git revert" > README.md
git add README.md
git commit -m "Commit inicial"
echo "- Canvi A" >> README.md
git commit -a -m "Canvi A"
echo "- Canvi B" >> README.md
git commit -a -m "Canvi B"
echo "- Canvi C" >> README.md
git commit -a -m "Canvi C"
echo "- Canvi D" >> README.md
git commit -a -m "Canvi D"
echo "- Canvi E" >> README.md
git commit -a -m "Canvi E"
git lga
jpuigcerver@fp:~ $ mkdir -p ~/git_revert
jpuigcerver@fp:~ $ cd ~/git_revert
jpuigcerver@fp:~/git_revert $ git init
Initialized empty Git repository in ~/git_revert/.git/
jpuigcerver@fp:~/git_revert (main) $ git branch -m main
jpuigcerver@fp:~/git_revert (main) $ echo "# Git revert" > README.md
jpuigcerver@fp:~/git_revert (main) $ git add README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -m "Commit inicial"
[main (root-commit) 2c18085] Commit inicial
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
jpuigcerver@fp:~/git_revert (main) $ echo "- Canvi A" >> README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -a -m "Canvi A"
[main aef9ebe] Canvi A
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_revert (main) $ echo "- Canvi B" >> README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -a -m "Canvi B"
[main e4b3412] Canvi B
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_revert (main) $ echo "- Canvi C" >> README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -a -m "Canvi C"
[main 3102fd3] Canvi C
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_revert (main) $ echo "- Canvi D" >> README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -a -m "Canvi D"
[main 9f735e9] Canvi D
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_revert (main) $ echo "- Canvi E" >> README.md
jpuigcerver@fp:~/git_revert (main) $ git commit -a -m "Canvi E"
[main 1e5c1df] Canvi E
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_revert (main) $ git lga
* 1e5c1df - (0 seconds ago) Canvi E - Joan Puigcerver (HEAD -> main)
* 9f735e9 - (0 seconds ago) Canvi D - Joan Puigcerver
* 3102fd3 - (0 seconds ago) Canvi C - Joan Puigcerver
* e4b3412 - (0 seconds ago) Canvi B - Joan Puigcerver
* aef9ebe - (0 seconds ago) Canvi A - Joan Puigcerver
* 2c18085 - (0 seconds ago) Commit inicial - Joan Puigcerver

Crea el nou repositori en una carpeta independent per evitar problemes amb els exemples i exercicis anteriors.

Exemple: git revert

Es desfà un commit del repositori.

jpuigcerver@fp:~/git_revert (main) $ git revert 1e5c1df --no-edit
[main 54e6def] Revert "Canvi E"
 Date: Tue Jan 21 12:40:44 2025 +0100
 1 file changed, 1 deletion(-)
jpuigcerver@fp:~/git_revert (main) $ git lga
* 54e6def - (0 seconds ago) Revert "Canvi E" - Joan Puigcerver (HEAD -> main)
* 1e5c1df - (0 seconds ago) Canvi E - Joan Puigcerver
* 9f735e9 - (0 seconds ago) Canvi D - Joan Puigcerver
* 3102fd3 - (0 seconds ago) Canvi C - Joan Puigcerver
* e4b3412 - (0 seconds ago) Canvi B - Joan Puigcerver
* aef9ebe - (0 seconds ago) Canvi A - Joan Puigcerver
* 2c18085 - (0 seconds ago) Commit inicial - Joan Puigcerver
jpuigcerver@fp:~/git_revert (main) $ git show
commit 54e6def6a69a5e3be15274ef8cdc4018c246a49f
Author: Joan Puigcerver <j.puigcerveribanez@edu.gva.es>
Date:   Tue Jan 21 12:40:44 2025 +0100

    Revert "Canvi E"

    This reverts commit 1e5c1df273107dc858ab41978fd9e117fae65808.

diff --git a/README.md b/README.md
index 4869b5e..2a58c68 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,3 @@
 - Canvi B
 - Canvi C
 - Canvi D
-- Canvi E

S'observa que s'ha creat un commit nou que inverteix els canvis, mentre que el commit original continua en la història.

Revertir diversos commits

L'acció revert només permet desfer un commit cada vegada. Per a desfer-ne diversos, es pot aplicar l'ordre revert successivament a cada commit amb l'opció --no-commit:

git revert --no-commit <ref>

Aquest procés posa el repositori en l'estat REVERTING i afig els canvis a l'Àrea de preparació (Staging Area). En aquest punt, es poden revertir més commits o finalitzar el procés amb git revert --continue.

Més informació: How can I revert multiple Git commits? – StackOverflow

Exemple: Revertir diversos commits

Es desfan diversos commits i es crea un únic commit amb tots els canvis.

jpuigcerver@fp:~/git_revert (main) $ git lga
* 54e6def - (0 seconds ago) Revert "Canvi E" - Joan Puigcerver (HEAD -> main)
* 1e5c1df - (0 seconds ago) Canvi E - Joan Puigcerver
* 9f735e9 - (0 seconds ago) Canvi D - Joan Puigcerver
* 3102fd3 - (0 seconds ago) Canvi C - Joan Puigcerver
* e4b3412 - (0 seconds ago) Canvi B - Joan Puigcerver
* aef9ebe - (0 seconds ago) Canvi A - Joan Puigcerver
* 2c18085 - (0 seconds ago) Commit inicial - Joan Puigcerver
jpuigcerver@fp:~/git_revert (main) $ git revert 9f735e9 --no-commit
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git status
On branch main
You are currently reverting commit 9f735e9.
  (all conflicts fixed: run "git revert --continue")
  (use "git revert --skip" to skip this patch)
  (use "git revert --abort" to cancel the revert operation)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

jpuigcerver@fp:~/git_revert (main|REVERTING) $ git diff --staged
diff --git a/README.md b/README.md
index 2a58c68..aa091c8 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,3 @@
 - Canvi A
 - Canvi B
 - Canvi C
-- Canvi D
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git revert 3102fd3 --no-commit
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git status
On branch main
You are currently reverting commit 3102fd3.
  (all conflicts fixed: run "git revert --continue")
  (use "git revert --skip" to skip this patch)
  (use "git revert --abort" to cancel the revert operation)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

jpuigcerver@fp:~/git_revert (main|REVERTING) $ git diff --staged
diff --git a/README.md b/README.md
index 2a58c68..395c8c6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
 # Git revert
 - Canvi A
 - Canvi B
-- Canvi C
-- Canvi D
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git commit -m "Revert \"Canvi C i D\"" # (1)!
[main 5ab52e3] Revert "Canvi C i D"
 1 file changed, 2 deletions(-)
jpuigcerver@fp:~/git_revert (main) $ git lga
* 5ab52e3 - (0 seconds ago) Revert "Canvi C i D" - Joan Puigcerver (HEAD -> main)
* 54e6def - (0 seconds ago) Revert "Canvi E" - Joan Puigcerver
* 1e5c1df - (0 seconds ago) Canvi E - Joan Puigcerver
* 9f735e9 - (0 seconds ago) Canvi D - Joan Puigcerver
* 3102fd3 - (0 seconds ago) Canvi C - Joan Puigcerver
* e4b3412 - (0 seconds ago) Canvi B - Joan Puigcerver
* aef9ebe - (0 seconds ago) Canvi A - Joan Puigcerver
* 2c18085 - (0 seconds ago) Commit inicial - Joan Puigcerver
jpuigcerver@fp:~/git_revert (main) $ git show
commit 5ab52e3a58485be85012a623d474942bf56b0e4f
Author: Joan Puigcerver <j.puigcerveribanez@edu.gva.es>
Date:   Tue Jan 21 12:40:44 2025 +0100

    Revert "Canvi C i D"

diff --git a/README.md b/README.md
index 2a58c68..395c8c6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
 # Git revert
 - Canvi A
 - Canvi B
-- Canvi C
-- Canvi D
  1. Per a eixir de l'estat REVERTING també es pot fer un git commit, que permet especificar un missatge.

Resolució de conflictes en un revert

Aquesta acció pot generar conflictes si els canvis que es volen desfer s'han modificat posteriorment. En aquest cas, el repositori passa a l'estat REVERTING i cal resoldre els conflictes manualment, de la mateixa manera que en una fusió de branques (merge).

Exemple: Resolució de conflictes en git revert

Es vol desfer el commit Canvi A, però els canvis de Canvi B depenen del primer commit. Per tant, git revert genera un conflicte i cal indicar manualment quin serà l'estat final del fitxer.

jpuigcerver@fp:~/git_revert (main) $ cat README.md
# Git revert
- Canvi A
- Canvi B
jpuigcerver@fp:~/git_revert (main) $ git lga
* 5ab52e3 - (1 second ago) Revert "Canvi C i D" - Joan Puigcerver (HEAD -> main)
* 54e6def - (1 second ago) Revert "Canvi E" - Joan Puigcerver
* 1e5c1df - (1 second ago) Canvi E - Joan Puigcerver
* 9f735e9 - (1 second ago) Canvi D - Joan Puigcerver
* 3102fd3 - (1 second ago) Canvi C - Joan Puigcerver
* e4b3412 - (1 second ago) Canvi B - Joan Puigcerver
* aef9ebe - (1 second ago) Canvi A - Joan Puigcerver
* 2c18085 - (1 second ago) Commit inicial - Joan Puigcerver
jpuigcerver@fp:~/git_revert (main) $ git revert aef9ebe
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not revert aef9ebe... Canvi A
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git revert --continue".
hint: You can instead skip this commit with "git revert --skip".
hint: To abort and get back to the state before "git revert",
hint: run "git revert --abort".
hint: Disable this message with "git config advice.mergeConflict false"
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git status
On branch main
You are currently reverting commit aef9ebe.
  (fix conflicts and run "git revert --continue")
  (use "git revert --skip" to skip this patch)
  (use "git revert --abort" to cancel the revert operation)

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
    both modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
jpuigcerver@fp:~/git_revert (main|REVERTING) $ code README.md # (1)!
jpuigcerver@fp:~/git_revert (main|REVERTING) $ cat README.md
# Git revert
- Canvi B
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git diff
diff --cc README.md
index 395c8c6,9f757b1..0000000
--- a/README.md
+++ b/README.md
@@@ -1,3 -1,1 +1,2 @@@
  # Git revert
- - Canvi A
 +- Canvi B
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git add README.md
jpuigcerver@fp:~/git_revert (main|REVERTING) $ git revert --continue --no-edit
[main 41d66b0] Revert "Canvi A"
 1 file changed, 1 deletion(-)
jpuigcerver@fp:~/git_revert (main) $ git lga
* 41d66b0 - (0 seconds ago) Revert "Canvi A" - Joan Puigcerver (HEAD -> main)
* 5ab52e3 - (1 second ago) Revert "Canvi C i D" - Joan Puigcerver
* 54e6def - (1 second ago) Revert "Canvi E" - Joan Puigcerver
* 1e5c1df - (1 second ago) Canvi E - Joan Puigcerver
* 9f735e9 - (1 second ago) Canvi D - Joan Puigcerver
* 3102fd3 - (1 second ago) Canvi C - Joan Puigcerver
* e4b3412 - (1 second ago) Canvi B - Joan Puigcerver
* aef9ebe - (1 second ago) Canvi A - Joan Puigcerver
* 2c18085 - (1 second ago) Commit inicial - Joan Puigcerver
  1. S'edita manualment el fitxer per a eliminar els marcadors de conflicte i la línia - Canvi A.
📌 Aquest document pot quedar desactualitzat després d’imprimir-lo. Pots consultar la versió més recent a la pàgina web.
🌿 Abans d’imprimir aquest document, considera si és realment necessari. Redueix el consum de paper i ajuda a protegir el nostre entorn.