Uso avanzado de Git¶
Deshacer cambios¶
Deshaciendo cambios antes de la fase de staging¶
Volvemos a la rama máster y vamos a modificar el comentario que pusimos:
$ git checkout main
Ya en 'main'
Modificamos curso-git-app.dylan
de la siguiente manera:
Module: curso-git-app
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
// TODO: cambiar "mundo" por constante $greeting
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
Y comprobamos:
$ git status
En la rama main
Cambios no rastreados para el commit:
(usa "git add <archivo>..." para actualizar lo que será confirmado)
(usa "git restore <archivo>..." para descartar los cambios en el directorio de trabajo)
modificados: curso-git-app.dylan
sin cambios agregados al commit (usa "git add" y/o "git commit -a")
El mismo Git nos indica que debemos hacer para añadir los cambios o para deshacerlos:
$ git restore curso-git-app.dylan
Comprobamos que todo está igual que antes de añadir el comentario:
$ git status
En la rama main
nada para hacer commit, el árbol de trabajo está limpio
$ cat curso-git-app.dylan
Deshaciendo cambios antes del commit¶
Vamos a hacer lo mismo que la vez anterior, añadiendo el comentario, pero esta vez sí añadiremos el cambio al staging (sin hacer commit).
Así que volvemos a modificar curso-git-app.dylan
igual que la
anterior ocasión:
Module: curso-git-app
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
// TODO: cambiar "mundo" por constante $greeting
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
Y lo añadimos al staging
$ git add curso-git-app.dylan
$ git status
En la rama main
Cambios a ser confirmados:
(usa "git restore --staged <archivo>..." para sacar del área de stage)
modificados: curso-git-app.dylan
De nuevo, Git nos indica qué debemos hacer para deshacer el cambio. Primero lo sacamos del stage:
$ git restore --staged curso-git-app.dylan
Después restauramos la copia de trabajo:
$ git restore curso-git-app.dylan
Y ya tenemos nuestro repositorio limpio otra vez. Como vemos hay que hacerlo en dos pasos: uno para borrar los datos del staging y otro para restaurar la copia de trabajo.
Deshaciendo commits no deseados¶
Si a pesar de todo hemos hecho un commit y nos hemos equivocado,
podemos deshacerlo con la orden git revert
.
Modificamos otra vez el archivo como antes:
Module: curso-git-app
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
// TODO: cambiar "mundo" por constante $greeting
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
Pero ahora sí hacemos commit:
$ git add curso-git-app
$ git commit -m "Ups... este commit está mal."
$git commit -m "Ups... este commit está mal."
[main 6354788] Ups... este commit está mal.
1 file changed, 1 insertion(+), 1 deletion(-)
Bien, una vez confirmado el cambio, vamos a deshacer el cambio con la
orden git revert
:
$ git revert HEAD --no-edit
[main a0d1cb3] Revert "Ups... este commit está mal."
Date: Fri Jul 5 08:53:28 2024 +0200
1 file changed, 1 deletion(-)
$ git log -2
$ git log -2
commit a0d1cb399a0b1cd6046f6a5d7ed768565ee54d13 (HEAD -> main)
Author: Fernando Raya <f...@gmail.com>
Date: Fri Jul 5 08:53:28 2024 +0200
Revert "Ups... este commit está mal."
This reverts commit 6354788c9b952524164084478e1f3ad9a7503fd2.
commit 6354788c9b952524164084478e1f3ad9a7503fd2
Author: Fernando Raya <f...@gmail.com>
Date: Fri Jul 5 08:51:22 2024 +0200
Ups... este commit está mal.
Borrar commits de una rama¶
El anterior apartado revierte un commit, pero deja huella en el
historial de cambios. Para hacer que no aparezca en el historial hay
que usar la orden git reset
. Volveremos a la versión v1.1 antes
del commit.
$ git reset --hard v1.1
Realizaremos el comando y miraremos como queda el repositorio:
$ git reset --hard v1.1
HEAD is now at f0b885f Añade README
$ git log -1
commit f0b885f0b6aa3e0d18ebcb5bd3df23f33ea3a09f (HEAD -> main, tag: v1.1)
Author: Fernando Raya <f...@gmail.com>
Date: Thu May 23 20:45:17 2024 +0200
Añade README
El resto de cambios no se han borrado (aún), simplemente no están accesibles porque git no sabe como referenciarlos. Si sabemos su hash podemos acceder aún a ellos. Pasado un tiempo, eventualmente Git tiene un recolector de basura que los borrará. Se puede evitar etiquetando el estado final.
Advertencia
La orden reset
es una operación delicada. Debe evitarse si no
se sabe bien lo que se está haciendo, sobre todo cuando se trabaja
en repositorios compartidos, porque podríamos alterar la historia
de cambios lo cual puede provocar problemas de sincronización.
Modificar un commit¶
Esto se usa cuando hemos olvidado añadir un cambio a un commit que
acabamos de realizar. Tenemos nuestro archivo
curso-de-git-app.dylan
de la siguiente manera:
Module: curso-de-git-app
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
Añadiremos el autor del programa:
Module: curso-de-git-app
Author: Fernando Raya
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
$ git commit -a -m "Añadido el autor del programa"
$ git commit -a -m "Añadido el autor del programa"
[main 910b3d8] Añadido el autor del programa
1 file changed, 1 insertion(+)
Truco
El parámetro -a
hace un git add
antes de hacer
commit de todos los archivos modificados o borrados (de los
nuevos no), con lo que nos ahorramos un paso.
$ git log -1
commit 910b3d874fb201362bb21e9e09eccac4661718ab (HEAD -> main)
Author: Fernando Raya <f...@gmail.com>
Date: Fri Jul 5 13:52:38 2024 +0200
Volvemos a modificar nuestro archivo:
Module: curso-de-git-app
Author: Fernando Raya
Email: <f...@gmail.com>
define function main
(name :: <string>, arguments :: <vector>)
// Si no hay argumentos poner mensaje por defecto
let mensaje = if (arguments.size < 1)
"mundo"
else
arguments[0]
end;
format-out("%s\n", greeting(mensaje));
exit-application(0);
end function;
// Calling our main function (which could have any name) should be the last
// thing we do.
main(application-name(), application-arguments());
Y en esta ocasión usamos commit --amend
que nos permite modificar
el último estado confirmado, sustituyéndolo por el estado actual:
$ git add curso-de-git-app.dylan
$ git commit --amend -m "Añadido el autor del programa y su email"
$ git commit --amend -m "Añadido el autor del programa y su email"
[main 1419047] Añadido el autor del programa y su email
Date: Fri Jul 5 13:52:38 2024 +0200
1 file changed, 1 insertion(+)
$ git log -2
commit 141904775d0029e6a8286887b9d013c7372ba787 (HEAD -> main)
Author: Fernando Raya <f...@gmail.com>
Date: Fri Jul 5 13:52:38 2024 +0200
Añadido el autor del programa y su email
commit f0b885f0b6aa3e0d18ebcb5bd3df23f33ea3a09f (tag: v1.1)
Author: Fernando Raya <f...@gmail.com>
Date: Thu May 23 20:45:17 2024 +0200
Añade README
Advertencia
Nunca modifiques un commit que ya hayas sincronizado con otro repositorio o que hayas recibido de él. Estarías alterando la historia de cambios y provocarías problemas de sincronización.
Moviendo y borrando archivos¶
Mover un archivo a otro directorio con git¶
Para mover archivos usaremos la orden git mv
. Dividiremos los
ficheros fuente en subdirectorios, uno para la librería y otro para la
aplicación:
$ mkdir -p source/lib
$ mkdir source/app
$ git mv curso-de-git.{dylan,lid} library.dylan source/lib
$ git status
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: curso-de-git.dylan -> source/lib/curso-de-git.dylan
renamed: curso-de-git.lid -> source/lib/curso-de-git.lid
renamed: library.dylan -> source/lib/library.dylan
git mv curso-de-git-app.{dylan,lid} curso-de-git-app-library.dylan source/app
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: curso-de-git-app-library.dylan -> source/app/curso-de-git-app-library.dylan
renamed: curso-de-git-app.dylan -> source/app/curso-de-git-app.dylan
renamed: curso-de-git-app.lid -> source/app/curso-de-git-app.lid
renamed: curso-de-git.dylan -> source/lib/curso-de-git.dylan
renamed: curso-de-git.lid -> source/lib/curso-de-git.lid
renamed: library.dylan -> source/lib/library.dylan
Guardaremos los cambios:
$ git commit -m "Reordenar ficheros en subdirectorios"
$ git commit -m "Reordenar ficheros en subdirectorios"
[main b386fd2] Reordenar ficheros en subdirectorios
6 files changed, 0 insertions(+), 0 deletions(-)
rename curso-de-git-app-library.dylan => source/app/curso-de-git-app-library.dylan (100%)
rename curso-de-git-app.dylan => source/app/curso-de-git-app.dylan (100%)
rename curso-de-git-app.lid => source/app/curso-de-git-app.lid (100%)
rename curso-de-git.dylan => source/lib/curso-de-git.dylan (100%)
rename curso-de-git.lid => source/lib/curso-de-git.lid (100%)
rename library.dylan => source/lib/library.dylan (100%)
Mover y borrar archivos¶
Podíamos haber hecho el paso anterior con la órden del sistema mv
y el resultado hubiera sido el mismo. Lo siguiente es a modo de
ejemplo y no es necesario que lo ejecutes:
$ mkdir -p source/{lib,app}
$ mv curso-de-git.{dylan,lid} library.dylan source/lib
$ mv curso-de-git-app.{dylan,lid} curso-de-git-app-library.dylan source/app
$ git add source/lib
$ git add source/app
$ git rm curso-de-git.{dylan,lid} library.dylan
$ git rm curso-de-git-app.{dylan,lid} curso-de-git-app-library.dylan
Y, ahora sí, ya podemos guardar los cambios:
$ git commit -m "Reordenar ficheros a subdirectorios"