Herramientas de Git

Reiniciar Desmitificado

Los Tres Arboles

Una manera facil de entender reset y checkout es pensar en Git como un administrador de contenido de tres arboles diferentes. Por “arbol” nos referimos a “coleccion de archivos”, no necesariamente a la estructura de datos.

ArbolRol
HEADUltima instantanea del commit, proximo padre
IndiceSiguiente instantanea del commit propuesta
Directorio de TrabajoCaja de arena

HEAD es el puntero a la referencia de la rama actual, que a su vez apunta al ultimo commit realizado en esa rama. HEAD sera el padre del proximo commit que se cree. En general, es mas simple pensarlo como la instantanea de tu ultimo commit.

git cat-file -p HEAD
git ls-tree -r HEAD

El Indice

El indice es tu siguiente commit propuesto, tambien conocido como el “Area de Preparacion”. Git lo rellena con una lista de todos los contenidos del archivo revisados por ultima vez en tu directorio de trabajo.

git ls-files -s

El Directorio de Trabajo

Los otros dos arboles almacenan su contenido de manera eficiente pero inconveniente dentro de la carpeta .git. El directorio de trabajo los descomprime en archivos reales, haciendo mucho mas facil editarlos. Piensalo como una caja de arena donde puedes probar cambios antes de enviarlos al indice y luego al historial.


El Flujo de Trabajo

El objetivo principal de Git es registrar instantaneas de tu proyecto en estados sucesivamente mejores, mediante la manipulacion de estos tres arboles.

Flujo de trabajo de los tres arboles

Visualicemos el proceso con un ejemplo. Supongamos que entras a un directorio nuevo con un solo archivo (v1). Ejecutas git init, lo que crea un repositorio con HEAD apuntando a una rama aun no nacida.

Estado inicial: solo el directorio de trabajo tiene contenido

Ejecutas git add para copiar el archivo al indice:

git add copia el archivo al indice

Luego git commit, que guarda el indice como una instantanea permanente y actualiza HEAD:

git commit guarda la instantanea y actualiza HEAD

Ahora modificas el archivo (v2) y repites el proceso:

v2 en el directorio de trabajo
git add copia v2 al indice
git commit guarda v2

El Papel del Reinicio

Supongamos que confirmamos el archivo por tercera vez (v3). Nuestro historial luce asi:

Historial con tres commits

reset manipula los tres arboles de forma simple y predecible, realizando hasta tres operaciones en orden.


Paso 1: Mover HEAD (--soft)

Lo primero que hace reset es mover la rama a la que apunta HEAD. Si HEAD esta en master, ejecutar git reset HEAD~ hara que master apunte al commit anterior.

reset --soft mueve HEAD al commit anterior

Con --soft, el comando se detiene aqui. Esto deshace el ultimo git commit sin tocar el indice ni el directorio de trabajo. Es equivalente a deshacer el commit y dejar todo preparado para volver a confirmar.


Paso 2: Actualizar el Indice (--mixed)

El siguiente paso es actualizar el indice con el contenido de la instantanea a la que ahora apunta HEAD.

reset --mixed actualiza el indice

Con --mixed (que es el comportamiento por defecto), el comando se detiene aqui. Esto deshace el ultimo commit y hace unstage de todo — retrocede a antes de ejecutar git add y git commit.


Paso 3: Actualizar el Directorio de Trabajo (--hard)

El tercer paso hace que el directorio de trabajo se parezca al indice.

reset --hard actualiza tambien el directorio de trabajo

Con --hard, el comando completa las tres operaciones. Deshace el ultimo commit, el git add, y todo el trabajo en el directorio de trabajo.

--hard es la unica forma de hacer que reset sea peligroso. Git destruira los datos del directorio de trabajo sin posibilidad facil de recuperacion. Usalo con cuidado.


Resumen de los tres modos

reset sobrescribe los tres arboles en orden especifico, deteniendose cuando se le indica:

  • Mueve HEAD de la rama -> (se detiene aqui si --soft)
  • Actualiza el indice para que se vea como HEAD -> (se detiene aqui si --mixed o sin opcion)
  • Actualiza el directorio de trabajo para que se vea como el indice -> (solo si --hard)

Ejercicio 01

Reset: los tres arboles y los tres modos

Entrar al kahoot y esperar el codigo de la sala, o presionar la opcion “Aprende” para responder de forma individual.


Reset con una Ruta

Si especificas una ruta de archivo, reset omite el paso 1 (no puede mover HEAD a solo parte de un commit) y limita su accion a ese archivo especifico.


Por ejemplo, git restore --staged file.txt es equivalente a git reset HEAD file.txt, que copia file.txt de HEAD al indice, haciendo unstage del archivo:

reset con ruta hace unstage del archivo

Tambien puedes especificar un commit concreto para extraer una version anterior de un archivo directamente al indice:

git reset eb43bf file.txt
reset con commit y ruta extrae una version anterior del archivo

Squash con Reset

Una tecnica util con reset --soft es aplastar (squash) varios commits en uno. Si tienes commits intermedios de trabajo en progreso:

Historial con commits de trabajo en progreso

Puedes ejecutar git reset --soft HEAD~2 para mover HEAD dos commits atras, dejando el indice intacto:

reset --soft mueve HEAD dos commits atras

Y luego hacer un nuevo git commit que los agrupa a todos en uno:

El nuevo commit agrupa el trabajo en progreso

Reset vs Checkout

checkout tambien manipula los tres arboles, pero con diferencias importantes respecto a reset:


Sin rutas: git checkout <rama> es similar a git reset --hard <rama>, pero con dos diferencias clave:

  • checkout es seguro para el directorio de trabajo: intenta una fusion trivial antes de sobrescribir, no destruye cambios sin avisar.
  • checkout mueve HEAD a otra rama; reset mueve la rama a la que HEAD apunta.
Diferencia entre checkout y reset respecto a HEAD

Con rutas: git checkout <commit> <archivo> actualiza el indice y el directorio de trabajo con esa version del archivo. No mueve HEAD, pero no es seguro para el directorio de trabajo porque sobrescribe el archivo sin avisar.


Tabla Resumen

ComandoHEADIndiceDir. TrabajoSeguro?
reset --soft [commit]REFNONOSI
reset [commit]REFSINOSI
reset --hard [commit]REFSISINO
checkout [commit]HEADSISISI
reset (commit) [file]NOSINOSI
checkout (commit) [file]NOSISINO

La columna HEAD dice “REF” si el comando mueve la rama a la que HEAD apunta, y “HEAD” si mueve el propio HEAD. Presta atencion especial a la columna “Seguro”: si dice NO, piensalo bien antes de ejecutar.


Ejercicio 02

Reset en accion

  • Descargar targz
  • Descomprimir con tar -xzf 16-reset-desmitificado.tar.gz
  • Entrar a la carpeta con cd 16-reset-desmitificado/
  • Abre tu editor de codigo (ej: code .) y lee el README.md

Recursos