<div class="page">
<div class="cover text-center">
<img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo">
# Reset i Amend
<div class="text-end fit-content ms-auto my-3 mt-auto pt-3">
<p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p>
<p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p>
<p><strong>Curs:</strong> 2024/2025</p>
</div>
<div>
<p class="fw-bold mb-0">Llicència: BY-NC-SA</p>
<p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p>
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank">
<img class="mx-auto" src="/itb/images/license.png" alt="Licence"/>
</a>
</div><!--license-->
</div><!--cover-->
</div><!--page-->
{:toc}
## Introducció
Les eines `git reset` i `git commit --amend` ens permeten 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.
Aquestes eines són molt potents, però cal tindre en compte que modificar la història del repositori,
especialment si ja s'han publicat els canvis (`push`), s'ha de fer en precaució, ja que pot ocasionar
problemes entre els col·laboradors del repositori.
## Repositori d'exemple
::: tip
Podeu copiar i pegar les ordres següents a __Git Bash__
per inicialitzar un repositori amb l'estructura dels exemples.
:::
Tots els exemples es realitzaran a partir d'un repositori amb la següent estructura:
```bash
mkdir ~/git_reset
cd ~/git_reset
git init
echo "# Git reset" >> README.md
git add README.md
git commit -m "Added README.md"
echo "- Primer canvi" >> README.md
git commit -a -m "Primer canvi"
echo "- Segon canvi" >> README.md
git commit -a -m "Segon canvi"
echo "- Tercer canvi" >> README.md
git commit -a -m "Tercer canvi"
```
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (2 seconds ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (30 seconds ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (47 seconds ago) Primer canvi - Joan Puigcerver
* 8790081 - (72 seconds ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git status
On branch main
nothing to commit, working tree clean
jpuigcerver@FP:~/git_reset (main) $ cat README.md
# Git reset
- Primer canvi
- Segon canvi
- Tercer canvi
```
## Reset
L'eina `git reset` s'utilitza per modificar l'estat actual del repositori
a un _commit_ en concret.
::: info
Aquesta opció mou la referència de la branca actual, on està situat el `HEAD`.
:::
::: docs
Documentació oficial de Git Reset: https://git-scm.com/docs/git-reset
:::
El seu comportament depén de les opcions especificades.
#3.1[Resum de l'eina Git Reset](/itb/DAM-ED/UD4/img/git_reset_resum.jpg)
### Soft (`--soft`)
L'opció `--soft` modifica l'estat del repositori a la referència especificada i conserva
els canvis realitzats en el _Directori de Treball_ i a l'_Àrea de Preparació (Staging Area)_.
```
git reset --soft <ref>
```
- `ref`: La referència pot ser l'identificador de un commit, una branca o una etiqueta.
::: example
Realitzem un `git reset --soft` per esborrar l'últim commit __Tercer canvi__:
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git reset --soft 707c110
jpuigcerver@FP:~/git_reset (main) $ git lga
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver (HEAD -> main)
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
.green{modified: README.md}
jpuigcerver@FP:~/git_reset (main) $ git diff --staged
diff --git a/README.md b/README.md
index db1ee0e..510c85b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
# Git reset
- Primer canvi
- Segon canvi
+- Tercer canvi
jpuigcerver@FP:~/git_reset (main) $ cat README.md
# Git reset
- Primer canvi
- Segon canvi
- Tercer canvi
```
Els canvis encara existeixen en el _Directori de Treball_ i en l'_Àrea de Preparació_.
Es pot tornar a crear el commit si es dessitja directament.
```shell
jpuigcerver@FP:~/git_reset (main) $ git commit -m "Tercer canvi"
[main 2b8827e] Tercer canvi
1 file changed, 1 insertion(+)
jpuigcerver@FP:~/git_reset (main) $ git lga
* 2b8827e - (2 seconds ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
```
:::
### Mixed (`--mixed`)
L'opció `--mixed` modifica l'estat del repositori a la referència especificada.
Els canvis es conserven en el _Directori de Treball_, però no a l'_Àrea de Preparació (Staging Area)_.
Aquest es el comportament per defecte si no s'especifica cap altra opció.
```
git reset [--mixed] <ref>
```
- L'opció `--mixed` és opcional, ja que és el comportament per defecte.
::: example
Realitzem un `git reset --mixed` per esborrar l'últim commit __Tercer canvi__:
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git reset --mixed 707c110
Unstaged changes after reset:
M README.md
jpuigcerver@FP:~/git_reset (main) $ git lga
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver (HEAD -> main)
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ 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)
.red{modified: README.md}
no changes added to commit (use "git add" and/or "git commit -a")
jpuigcerver@FP:~/git_reset (main) $ git diff
diff --git a/README.md b/README.md
index db1ee0e..510c85b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
# Git reset
- Primer canvi
- Segon canvi
+- Tercer canvi
jpuigcerver@FP:~/git_reset (main) $ cat README.md
# Git reset
- Primer canvi
- Segon canvi
- Tercer canvi
```
Els canvis encara existeixen en el _Directori de Treball_.
Es pot tornar a crear el commit si es dessitja, però primer cal afegir els canvis a l'_Àrea de Preparació_.
```shell
jpuigcerver@FP:~/git_reset (main) $ git add README.md
jpuigcerver@FP:~/git_reset (main) $ git commit -m "Tercer canvi"
[main 2b8827e] Tercer canvi
1 file changed, 1 insertion(+)
jpuigcerver@FP:~/git_reset (main) $ git lga
* 2b8827e - (2 seconds ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
```
:::
### Hard (`--hard`)
L'opció `--hard` modifica l'estat del repositori i l'_Àrea de Preparació_,
revertint el repositori a la referència especificada.
Els canvis no es conservern en el _Directori de Treball_ ni en l'_Àrea de Preparació_.
```
git reset --hard <ref>
```
::: danger
Compte! Tots els canvis es descarten permanentment.
:::
::: example
Realitzem un `git reset --hard` per esborrar l'últim commit __Tercer canvi__:
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git reset --hard 707c110
HEAD is now at 707c110 Segon canvi
jpuigcerver@FP:~/git_reset (main) $ git lga
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver (HEAD -> main)
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ git status
On branch main
nothing to commit, working tree clean
jpuigcerver@FP:~/git_reset (main) $ cat README.md
# Git reset
- Primer canvi
- Segon canvi
```
Els canvis s'han descartat i no es poden recuperar.
:::
### Keep (`--keep`)
L'opció `--keep` és molt similar al comportament per defecte.
En aquest cas, no permet realitzar el `reset` si això comporta
serien sobrescrits els canvis actuals del _Directori de Treball_
que no han segut confirmats (`commit`).
```
git reset --keep <ref>
```
::: example
Realitzem un `git reset --keep` per esborrar l'últim commit __Tercer canvi__,
però s'ha fet un canvi al fitxer README.md abans:
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ echo "- Quart canvi" >> README.md
jpuigcerver@FP:~/git_reset (main) $ 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)
.red{modified: README.md}
no changes added to commit (use "git add" and/or "git commit -a")
jpuigcerver@FP:~/git_reset (main) $ git reset --keep 707c110
error: Entry 'README.md' not uptodate. Cannot merge.
fatal: Could not reset index file to revision '707c110'.
```
Realitzar el reset suposaria pedre els canvis realitzats, per tant el reset no es porta a terme.
:::
## Amend
L'opció `git commit --amend` permet realitzar canvis a l'últim commit realitzat.
Això et permet modificar el missatge de l'últim commit, afegir nous fitxers o afegir
nous canvis els fitxers del repositori, inclòs els que han segut modificats en aquest últim commit.
La sintaxi és:
```bash
git commit --amend
```
Si no s'especifica cap missatge, s'obrirà l'editor de text definit (configurat amb `core.editor`)
amb el missatge anterior.
:::: example
Realitzem el commit __Quart canvi__ amb canvis:
```shell
jpuigcerver@FP:~/git_reset (main) $ git lga
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver (HEAD -> main)
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
jpuigcerver@FP:~/git_reset (main) $ echo "- Quart" >> README.md
jpuigcerver@FP:~/git_reset (main) $ git commit -a -m "Quart"
[main 04e87d6] Quart
1 file changed, 1 insertion(+)
jpuigcerver@FP:~/git_reset (main) $ git lga
* 04e87d6 - (1 second ago) Quart - Joan Puigcerver (HEAD -> main)
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
```
Volem modificar el fitxer perquè els canvis siguen consistents i afegir la paraula "canvi".
Modifiquem el commit:
```shell
jpuigcerver@FP:~/git_reset (main) $ nano README.md
jpuigcerver@FP:~/git_reset (main) $ git diff
diff --git a/README.md b/README.md
index 137a821..a44c9ce 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,4 @@
- Primer canvi
- Segon canvi
- Tercer canvi
-- Quart
+- Quart canvi
jpuigcerver@FP:~/git_reset (main) $ git commit -a --amend -m "Quart canvi"
[main 163e5cf] Quart canvi
Date: Mon Dec 11 16:16:24 2023 +0100
1 file changed, 1 insertion(+)
jpuigcerver@FP:~/git_reset (main) $ git lga
* 163e6cf - (1 second ago) Quart canvi - Joan Puigcerver (HEAD -> main)
* 90a3d19 - (5 minutes ago) Tercer canvi - Joan Puigcerver
* 707c110 - (5 minutes ago) Segon canvi - Joan Puigcerver
* 5266ed4 - (5 minutes ago) Primer canvi - Joan Puigcerver
* 8790081 - (5 minutes ago) Added README.md - Joan Puigcerver
```
::: note
Fixeu-vos amb que el _hash_ del _commit_ ha canvit. Això es deu a que Git ha creat un nou _commit_ i, per tant, la història ha segut modificada.
:::
::::
## Bibliografia
- https://stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-hard
- https://git-scm.com/docs/git-reset