Salta el contingut
 

Reset

Joan Puigcerver Ibáñez

j.puigcerveribanez@edu.gva.es

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Reset

L'ordre git reset ens permet moure la referència de la branca actual a qualsevol altre commit del repositori. Això significa que podem modificar la història del repositori local, per ajustar o refer la història a les nostres necessitats.

Algunes de les accions que podem fer mitjançant aquestes eines són:

  • Desfer o modificar commits anteriors.
  • Reorganitzar els commits abans de publicar-los.
  • Moure punters de les branques.

Perill

Aquestes eines són molt potents, però cal tindre en compte que modificar la història del repositori pot ser perillós.

Especialment, en les branques que ja han segut publicades (push), ja que pot ocasionar problemes entre els col·laboradors del repositori.

Funcionament de git reset

Figura 1. Funcionament de git reset

Al moure la referència d'una branca, podem deixar enrere commits amb els seus canvis corresponents. El com es gestionen aquests canvis dependrà del mode amb el qual executem l'ordre git reset:

  • --soft: Els canvis es conservaran a l'Àrea de Preparació.
  • --mixed: Comportament per defecte. Els canvis es conservaran al Directori de Treball.
  • --hard: Els canvis es descartaran.

Resum de l'eina git reset

Figura 2. Resum de l'eina git reset.

A més, aquesta ordre pot provocar que alguns commits perden totes les referències i, per tant, seran esborrats pel recol·lector de brossa de Git.

Exemple

A la Figura 1 els commits Canvi B i Canvi C seran esborrats perquè han perdut tots les referències.

Preparació del repositori

Danger

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

setup_reset.sh
#!/bin/bash

# Elimina els repositoris si existeixen
if [ -d ~/git_reset ]; then
    rm -rf ~/git_reset
fi

mkdir -p ~/git_reset
cd ~/git_reset
git init
git branch -m main
echo "# Git reset i commit --amend" > 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"
git lga
jpuigcerver@fp:~ $ mkdir -p ~/git_reset
jpuigcerver@fp:~ $ cd ~/git_reset
jpuigcerver@fp:~/git_reset $ git init
Initialized empty Git repository in ~/git_reset/.git/
jpuigcerver@fp:~/git_reset $ git branch -m main
jpuigcerver@fp:~/git_reset $ echo "# Git reset i commit --amend" > README.md
jpuigcerver@fp:~/git_reset $ git add README.md
jpuigcerver@fp:~/git_reset $ git commit -m "Commit inicial"
[main (root-commit) 5f92181] Commit inicial
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
jpuigcerver@fp:~/git_reset $ echo "- Canvi A" >> README.md
jpuigcerver@fp:~/git_reset $ git commit -a -m "Canvi A"
[main ff64d47] Canvi A
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_reset $ echo "- Canvi B" >> README.md
jpuigcerver@fp:~/git_reset $ git commit -a -m "Canvi B"
[main 8999e85] Canvi B
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_reset $ echo "- Canvi C" >> README.md
jpuigcerver@fp:~/git_reset $ git commit -a -m "Canvi C"
[main 99d1cc1] Canvi C
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_reset $ git lga
* 99d1cc1 - (0 seconds ago) Canvi C - Joan Puigcerver (HEAD -> main)
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Sintaxi general

Informació

Aquesta ordre mou la referència de la branca actual, on està situat el HEAD.

La sintaxi de l'ordre git reset és:

git reset [--soft | --mixed | --hard | --keep] <ref>

  • ref: La referència pot ser l'identificador de un commit, una branca o una etiqueta.

Documentació oficial de Git

git reset

Soft

El mode reset --soft mou la referència de la branca actual al commit especificat, conservant els canvis perduts a l'Àrea de Preparació (Staging Area).

git reset --soft <ref>
Exemple: reset --soft

Establim la referencia de la branca main al commit Canvi B.

En aquest cas, es perdran els canvis del commit Canvi C, que es conservaran en l'Àrea de Preparació.

jpuigcerver@fp:~/git_reset $ git reset --soft 8999e85
jpuigcerver@fp:~/git_reset $ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

jpuigcerver@fp:~/git_reset $ git diff --staged
diff --git a/README.md b/README.md
index dc7fc7d..d05d0d2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # Git reset i commit --amend
 - Canvi A
 - Canvi B
+- Canvi C
jpuigcerver@fp:~/git_reset $ git lga
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver (HEAD -> main)
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Creem de nou el commit Canvi C.

jpuigcerver@fp:~/git_reset $ git commit -m "Canvi C"
[main 99d1cc1] Canvi C
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_reset $ git lga
* 99d1cc1 - (0 seconds ago) Canvi C - Joan Puigcerver (HEAD -> main)
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Mixed

El mode reset --mixed mou la referència de la branca actual al commit especificat. Els canvis es conserven en el Directori de Treball.

Aquest es el comportament per defecte si no s'especifica cap altra opció.

git reset --mixed <ref>
Exemple: reset --mixed

Establim la referencia de la branca main al commit Canvi B.

En aquest cas, es perdran els canvis del commit Canvi C, que es conservaran en el Directori de Treball.

jpuigcerver@fp:~/git_reset $ git reset --mixed 8999e85
Unstaged changes after reset:
M   README.md
jpuigcerver@fp:~/git_reset $ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
jpuigcerver@fp:~/git_reset $ git diff
diff --git a/README.md b/README.md
index dc7fc7d..d05d0d2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # Git reset i commit --amend
 - Canvi A
 - Canvi B
+- Canvi C
jpuigcerver@fp:~/git_reset $ git lga
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver (HEAD -> main)
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Creem de nou el commit Canvi C.

jpuigcerver@fp:~/git_reset $ git add README.md
jpuigcerver@fp:~/git_reset $ git commit -m "Canvi C"
[main 99d1cc1] Canvi C
 1 file changed, 1 insertion(+)
jpuigcerver@fp:~/git_reset $ git lga
* 99d1cc1 - (0 seconds ago) Canvi C - Joan Puigcerver (HEAD -> main)
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Hard

El mode reset --hard mou la referència de la branca actual al commit especificat. modificant l'estat del repositori i revertint-lo a la referència especificada.

Perill

Tots els canvis es descarten permanentment.

git reset --hard <ref>
Exemple: reset --hard

Establim la referencia de la branca main al commit Canvi B.

En aquest cas, es perdran els canvis del commit Canvi C, que no es conservaran enlloc i no es podran recuperar.

jpuigcerver@fp:~/git_reset $ git reset --hard 8999e85
HEAD is now at 8999e85 Canvi B
jpuigcerver@fp:~/git_reset $ git status
On branch main
nothing to commit, working tree clean
jpuigcerver@fp:~/git_reset $ git lga
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver (HEAD -> main)
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Keep

El mode reset --keep és molt similar al comportament per defecte.

En aquest cas, no permet realitzar el reset si això comporta que els canvis actuals del Directori de Treball siguen sobreescrits per els canvis de l'operació de reset.

git reset --keep <ref>
Exemple: reset --keep

Com que realitzar el reset comportaria sobreescriure els canvis del Directori de Treball, l'operació no es realitza.

jpuigcerver@fp:~/git_reset $ echo "- Canvi C" >> README.md
jpuigcerver@fp:~/git_reset $ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
jpuigcerver@fp:~/git_reset $ git reset --keep ff64d47
error: Entry 'README.md' not uptodate. Cannot merge.
fatal: Could not reset index file to revision 'ff64d47'.
jpuigcerver@fp:~/git_reset $ git lga
* 8999e85 - (0 seconds ago) Canvi B - Joan Puigcerver (HEAD -> main)
* ff64d47 - (0 seconds ago) Canvi A - Joan Puigcerver
* 5f92181 - (0 seconds ago) Commit inicial - Joan Puigcerver

Bibliografia

📌 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.