{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Recuperar lo que creías perdido\n",
    "\n",
    "El reflog, que es la red de seguridad que nadie te contó\n",
    "\n",
    "Cuaderno de práctica del capítulo 25 de **Git desde cero**, de Miss Yera.\n",
    "\n",
    "Corre de arriba abajo. Si lo abres en Google Colab no necesitas instalar nada.\n",
    "\n",
    "Capítulo completo: https://missyera.com/guias/git-desde-cero/recuperar-lo-perdido/\n",
    "\n",
    "Los ejercicios están al final y traen una celda vacía debajo de cada uno. Las\n",
    "respuestas viven en el cuaderno de soluciones, y merece la pena pelearse un\n",
    "rato antes de abrirlo 💛"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Antes de empezar\n",
    "\n",
    "Este capítulo son comandos de terminal, no Python. La celda de abajo baja el\n",
    "ayudante que los ejecuta y que **recuerda en qué carpeta quedaste**, que es lo\n",
    "que hace falta para que un `cd` de una celda siga valiendo en la siguiente.\n",
    "\n",
    "A partir de ahí, cada celda de comandos empieza por `%%consola`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib.request\n",
    "\n",
    "# El ayudante de los cuadernos. Trae la corrección de los ejercicios y, en los\n",
    "# capítulos de consola, la celda mágica que ejecuta los comandos. Se baja en\n",
    "# vez de venir pegado aquí para que siempre sea el último.\n",
    "urllib.request.urlretrieve(\n",
    "    \"https://missyera.com/static/cuadernos/revisa.py\", \"revisa.py\")\n",
    "import revisa\n",
    "revisa.carga({\n",
    "    1: \"OWYzNzY2NiBFbnRyYSBlbCByZXBvcnRlIHBvciBjYW5hbAo0Y2I1MTlhIEVudHJhIGVsIG1pbmltYXJrZXQgZGUgVHJ1amlsbG8KYTk4NzRhZSBDYXRhbG9nbyBpbmljaWFsIGRlIGJvZGVnYXM=\",\n",
    "    2: \"SEVBRCBpcyBub3cgYXQgYTk4NzRhZSBDYXRhbG9nbyBpbmljaWFsIGRlIGJvZGVnYXMKYTk4NzRhZSBDYXRhbG9nbyBpbmljaWFsIGRlIGJvZGVnYXMKYm9kZWdhcy5jc3Y=\",\n",
    "    3: \"YTk4NzRhZSBIRUFEQHswfTogcmVzZXQ6IG1vdmluZyB0byBIRUFEfjIKOWYzNzY2NiBIRUFEQHsxfTogY29tbWl0OiBFbnRyYSBlbCByZXBvcnRlIHBvciBjYW5hbAo0Y2I1MTlhIEhFQURAezJ9OiBjb21taXQ6IEVudHJhIGVsIG1pbmltYXJrZXQgZGUgVHJ1amlsbG8KYTk4NzRhZSBIRUFEQHszfTogY29tbWl0IChpbml0aWFsKTogQ2F0YWxvZ28gaW5pY2lhbCBkZSBib2RlZ2Fz\",\n",
    "    4: \"SEVBRCBpcyBub3cgYXQgOWYzNzY2NiBFbnRyYSBlbCByZXBvcnRlIHBvciBjYW5hbAo5ZjM3NjY2IEVudHJhIGVsIHJlcG9ydGUgcG9yIGNhbmFsCjRjYjUxOWEgRW50cmEgZWwgbWluaW1hcmtldCBkZSBUcnVqaWxsbwphOTg3NGFlIENhdGFsb2dvIGluaWNpYWwgZGUgYm9kZWdhcwpib2RlZ2FzLmNzdgpjYW5hbGVzLmNzdg==\",\n",
    "    5: \"RGVsZXRlZCBicmFuY2ggcHJlY2lvcy1wb3ItY2FuYWwgKHdhcyA2YTNjZjdiKS4KY2FuYWwsbW9udG8KQm9kZWdhcyw0MjAwCkhvcmVjYSwzMTAwCiAgbWFpbgoqIHByZWNpb3MtcmVjdXBlcmFkbw==\",\n",
    "    6: \"OWYzNzY2NiByZXNldDogbW92aW5nIHRvIEhFQURAezF9CmE5ODc0YWUgcmVzZXQ6IG1vdmluZyB0byBIRUFEfjIKOWYzNzY2NiBjb21taXQ6IEVudHJhIGVsIHJlcG9ydGUgcG9yIGNhbmFsCjRjYjUxOWEgY29tbWl0OiBFbnRyYSBlbCBtaW5pbWFya2V0IGRlIFRydWppbGxvCmE5ODc0YWUgY29tbWl0IChpbml0aWFsKTogQ2F0YWxvZ28gaW5pY2lhbCBkZSBib2RlZ2Fz\",\n",
    "    7: \"ZmF0YWw6IGxvZyBmb3IgJ0hFQUQnIG9ubHkgaGFzIDEwIGVudHJpZXM=\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este es el capítulo que hace que se te quite el miedo, y por eso lo pongo\n",
    "antes que nada de la parte que sigue. Casi todo lo que crees que perdiste está\n",
    "ahí 🧯\n",
    "\n",
    "La frase que me han dicho más veces es \"borré tres días de trabajo\". Y casi\n",
    "siempre la respuesta cabe en una línea."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El log y el reflog no son lo mismo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|  | `git log` | `git reflog` |\n",
    "|---|---|---|\n",
    "| Qué muestra | La historia oficial | Cada vez que te moviste |\n",
    "| Incluye lo que \"borraste\" | No | Sí |\n",
    "| Se comparte | Sí | No, es de tu máquina |\n",
    "| Cuánto dura | Para siempre | 90 días por defecto |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eso de que el reflog no se comparte importa: es tuyo y de tu carpeta. Si\n",
    "clonas de nuevo el proyecto, el reflog no viene 🧳"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Perder algo a propósito"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Armamos un proyecto con historia y lo rompemos:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir ventas-miss-yera\n",
    "cd ventas-miss-yera\n",
    "git init -q\n",
    "printf 'ciudad,monto\\nLima,1200\\n' > ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Primeras ventas de Lima\"\n",
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Entran las ventas de Arequipa\"\n",
    "printf 'canal,monto\\nBodegas,4200\\n' > canales.csv\n",
    "git add canales.csv\n",
    "git commit -q -m \"Entra el reporte por canal\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres commits. Y ahora el desastre clásico:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reset --hard HEAD~2\n",
    "git log --oneline\n",
    "ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un commit, un archivo, y el reporte por canal desapareció. Este es el\n",
    "momento del \"se me fue el trabajo de dos días\" 😰"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El reflog"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reflog"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está todo. Cada línea es un movimiento, con su hash y qué lo causó. El\n",
    "`HEAD@{1}` es \"donde estabas justo antes\", `HEAD@{2}` el\n",
    "anterior, y así 🧭"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Volver"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reset --hard HEAD@{1}\n",
    "git log --oneline\n",
    "ls\n",
    "cat canales.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Los tres commits de vuelta y el archivo también. Eso es todo el\n",
    "capítulo 🎉"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Volver a un hash concreto"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuando hay muchos movimientos, es más seguro copiar el hash de la línea que\n",
    "quieres que contar posiciones:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reset --hard HEAD~1\n",
    "git log --oneline\n",
    "git reflog --format=\"%h %gs\" | head -4"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese hash de la izquierda se copia y se usa directamente. No hay que\n",
    "acordarse de nada."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Una rama borrada también vuelve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q -c reporte-por-ciudad\n",
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Entran las ventas de Cusco\"\n",
    "git switch -q -\n",
    "git branch -D reporte-por-ciudad\n",
    "git branch\n",
    "git reflog --format=\"%h %gs\" | head -3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La rama ya no está en la lista, pero su commit sigue en el reflog. Se\n",
    "recupera creando una rama nueva en ese punto:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q -c reporte-recuperado HEAD@{1}\n",
    "git log --oneline -2\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cusco volvió. Borrar una rama nunca borra sus commits, solo quita el\n",
    "nombre 🏷️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo único que no vuelve"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lo que nunca fue commit. Si editaste un archivo y no hiciste\n",
    "`git add` ni `commit`, Git no tiene copia y no hay nada\n",
    "que recuperar.\n",
    "\n",
    "De ahí la costumbre que me ahorra sustos: **antes de cualquier cosa\n",
    "que suene peligrosa, un commit**, aunque el mensaje diga \"a medias\". Se\n",
    "puede limpiar después 🧷"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Te equivocaste de rama y guardaste tres commits donde no era. Buscas cómo deshacer, encuentras un `reset --hard` en un foro y lo pegas.\n",
    "\n",
    "```\n",
    "$ git reset --hard HEAD~3\n",
    "HEAD is now at 3c1f80a Primeras ventas de Lima\n",
    "\n",
    "$ git log --oneline\n",
    "3c1f80a Primeras ventas de Lima\n",
    "\n",
    "# y los tres commits del reporte por canal?\n",
    "```\n",
    "\n",
    "**¿Qué está mal?** La respuesta está en el cuaderno de soluciones. Míralo tú primero."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Hiciste `git reset --hard` y tu `log` perdió tres commits. ¿Qué haces?\n",
    "\n",
    "a) `git reflog` y vuelvo al punto anterior\n",
    "\n",
    "b) Clono el proyecto otra vez desde GitHub\n",
    "\n",
    "c) Los vuelvo a escribir, no queda otra\n",
    "\n",
    "d) Busco los archivos en la papelera del sistema"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Construye algo que perder\n",
    "\n",
    "Tres commits en el catálogo de bodegas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Rómpelo\n",
    "\n",
    "Un reset duro de dos commits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Mira el reflog\n",
    "\n",
    "Todos tus movimientos, incluidos los que el log ya no\n",
    "muestra."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Vuelve\n",
    "\n",
    "Recupera los tres commits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Borra una rama y recupérala\n",
    "\n",
    "Las ramas borradas también vuelven."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Mira el reflog de una rama concreta\n",
    "\n",
    "El reflog también existe por rama, no solo para\n",
    "`HEAD`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Pide un punto del reflog que no existe\n",
    "\n",
    "Prueba a pedir un movimiento muy anterior en un\n",
    "repositorio recién creado."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 7\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Casi nada se pierde: el reflog guarda 90 días de movimientos. Lo\n",
    "único irrecuperable es lo que nunca fue commit.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 25 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/recuperar-lo-perdido/\n",
    "\n",
    "Que tengas lindo día! 🌸"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
