{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cambiar de tarea a mitad de camino\n",
    "\n",
    "Guardar lo que llevas sin hacer un commit del que te arrepientas\n",
    "\n",
    "Cuaderno de soluciones del capítulo 8 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/guardar-a-medias/\n",
    "\n",
    "Este es el cuaderno de **soluciones**. Trae el código de cada ejercicio, la\n",
    "explicación de la trampa y la respuesta del quiz. Si vienes del cuaderno de\n",
    "práctica sin haberlo intentado, vuelve 🙂"
   ]
  },
  {
   "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({}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El problema"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Estás a mitad del reporte de ventas por canal. No está terminado, no vale la\n",
    "pena guardarlo. Y entra un WhatsApp: hay que arreglar algo urgente ahora\n",
    "mismo.\n",
    "\n",
    "Tienes tres opciones y dos son malas: hacer un commit de algo a medias y\n",
    "ensuciar la historia, o perder lo que llevas. La tercera es el cajón."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir tienda\n",
    "cd tienda\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",
    "printf 'reporte a medias\\n' > reporte.txt\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Al cajón"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash push -u -m \"Reporte por canal a medias\"\n",
    "git status --short\n",
    "ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Carpeta limpia y `reporte.txt` desapareció. No se perdió: está\n",
    "guardado aparte, y ahora puedes hacer el arreglo urgente con el proyecto tal\n",
    "como estaba 🧹\n",
    "\n",
    "Ese `-u` importa. Sin él, los archivos que Git todavía no conoce\n",
    "(los del capítulo 4, los *untracked*) se quedan\n",
    "en la carpeta y el cajón se los salta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ver qué hay en el cajón"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Se pueden guardar varios y por eso llevan número. El `{0}` es el\n",
    "más reciente. Y el mensaje que pusiste con `-m` es lo que te salva\n",
    "cuando hay tres y no te acuerdas de cuál era cuál."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El arreglo urgente"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'canal,meta\\nBodegas,8000\\n' > metas.csv\n",
    "git add metas.csv\n",
    "git commit -q -m \"Urgente, entran las metas por canal\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y sacar lo tuyo del cajón"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash pop\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Todo de vuelta, encima del arreglo urgente. `pop` saca y borra del\n",
    "cajón; `apply` saca y lo deja ahí por si acaso."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error de sacar de un cajón vacío"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Esto revienta a propósito**, y de eso va. La celda te muestra la queja igual que te la mostraría tu terminal."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash pop"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "No stash entries found.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Corto y claro. Si te sale esto y sabes que guardaste algo, casi siempre es\n",
    "que estás en otro repositorio: **el cajón es de cada proyecto**, no\n",
    "de la máquina."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Guardas lo que llevas en el cajón, haces el arreglo urgente y te vas a almorzar. Al volver sigues con otra cosa, y a la semana te acuerdas del reporte.\n",
    "\n",
    "```\n",
    "$ git stash list\n",
    "\n",
    "stash@{0}: On main: Reporte por canal\n",
    "stash@{1}: On main: Prueba del IGV\n",
    "stash@{2}: On main: WIP on main: 8a2b19c\n",
    "stash@{3}: On main: WIP on main: 3c1f80a\n",
    "stash@{4}: On main: WIP on main: 5d9c2f1\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "El cajón se convirtió en un cementerio 🪦\n",
    "\n",
    "El stash está pensado para minutos, no para semanas. Los tres de abajo ni siquiera tienen mensaje, porque se guardaron sin `-m`: dicen \"WIP\" y el hash del commit donde estabas, que dentro de una semana no le dice nada a nadie.\n",
    "\n",
    "Y hay algo peor que el desorden: **el stash no se sube a ningún lado**. No viaja a GitHub, no lo ve nadie del equipo y no está en ninguna copia de seguridad. Si se malogra tu laptop, eso se va.\n",
    "\n",
    "La regla que uso: si algo va a pasar la noche en el cajón, no va al cajón. Va a una rama con un commit, aunque el mensaje diga que está a medias."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Llevas dos días de trabajo a medias y te vas de vacaciones. ¿Dónde lo dejas?\n",
    "\n",
    "a) En el stash, que para eso está\n",
    "\n",
    "b) En una rama, con un commit aunque esté a medias\n",
    "\n",
    "c) Sin guardar, total nadie va a tocar la laptop\n",
    "\n",
    "d) En el stash pero con un mensaje bien claro\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la b.**\n",
    "\n",
    "*a)* El stash no se sube a ningún lado ni lo ve nadie. Dos días de trabajo en un sitio que solo existe en tu laptop es mucho riesgo.\n",
    "\n",
    "*c)* Todo lo que no está en un commit es lo único que Git no puede recuperarte. Es justo lo que no hay que dejar suelto.\n",
    "\n",
    "*d)* El mensaje ayuda a encontrarlo, pero no resuelve lo importante: sigue estando solo en tu máquina.\n",
    "\n",
    "El cajón es para minutos. Para días, una rama 🌿"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Guarda un cambio y limpia\n",
    "\n",
    "Toca el CSV, mándalo al cajón y comprueba que la carpeta\n",
    "quedó limpia."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git stash push -m \"Cusco pendiente de confirmar\"\n",
    "git status --short\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "Saved working directory and index state On main: Cusco pendiente de confirmar\n",
    "?? reporte.txt\n",
    "ciudad,monto\n",
    "Lima,1200\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cusco desapareció del archivo y el estado está limpio. Todo lo que había se\n",
    "fue al cajón de una pieza."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Mira el cajón\n",
    "\n",
    "Lista lo que hay guardado."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "stash@{0}: On main: Cusco pendiente de confirmar\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un solo cajón, con el mensaje que le pusiste. Con dos o tres, este mensaje\n",
    "es la diferencia entre encontrarlo y adivinar."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Espía sin sacar\n",
    "\n",
    "Mira qué hay dentro del cajón sin recuperarlo todavía."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash show -p stash@{0}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "diff --git a/ventas.csv b/ventas.csv\n",
    "index b5256c1..7a40551 100644\n",
    "--- a/ventas.csv\n",
    "+++ b/ventas.csv\n",
    "@@ -1,2 +1,4 @@\n",
    " ciudad,monto\n",
    " Lima,1200\n",
    "+Arequipa,890\n",
    "+Cusco,760\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La línea con `+` es lo que guardaste. Poder mirar antes de sacar\n",
    "evita el clásico \"creo que era esto\" 👓"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Sácalo dejando copia\n",
    "\n",
    "Usa `apply` en vez de `pop` y\n",
    "comprueba que el cajón sigue lleno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash apply\n",
    "git stash list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "On branch main\n",
    "Changes not staged for commit:\n",
    "  (use \"git add <file>...\" to update what will be committed)\n",
    "  (use \"git restore <file>...\" to discard changes in working directory)\n",
    "\tmodified:   ventas.csv\n",
    "\n",
    "Untracked files:\n",
    "  (use \"git add <file>...\" to include in what will be committed)\n",
    "\treporte.txt\n",
    "\n",
    "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n",
    "stash@{0}: On main: Cusco pendiente de confirmar\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El cambio volvió a la carpeta y el cajón no se vació. Es lo que uso cuando no\n",
    "estoy segura de que ese cambio vaya a servir."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Vacía el cajón a mano\n",
    "\n",
    "Tira el cajón que ya recuperaste."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash drop\n",
    "git stash list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "Dropped refs/stash@{0} (0e7503f345cc2eb7215b1d8e2e662dcfbb0929ca)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sin salida porque ya no queda nada. `drop` borra uno,\n",
    "`clear` borra todos, y de esos dos no se vuelve 🧨"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Guarda también lo que Git no conoce\n",
    "\n",
    "Crea un archivo nuevo de clientes y guárdalo con\n",
    "`-u`, que es el que se lleva los desconocidos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'bodega,ciudad\\nBodega Inti,Cusco\\n' > clientes.csv\n",
    "git stash push -u -m \"Catalogo de clientes por revisar\"\n",
    "ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "Saved working directory and index state On main: Catalogo de clientes por revisar\n",
    "metas.csv\n",
    "ventas.csv\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sin el `-u`, ese archivo se habría quedado en la carpeta y el\n",
    "cajón lo habría ignorado. Es el olvido más común del stash."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Saca de un cajón que ya vaciaste\n",
    "\n",
    "Recupera lo guardado y después intenta sacar otra vez."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash pop\n",
    "git stash pop"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "On branch main\n",
    "Changes not staged for commit:\n",
    "  (use \"git add <file>...\" to update what will be committed)\n",
    "  (use \"git restore <file>...\" to discard changes in working directory)\n",
    "\tmodified:   ventas.csv\n",
    "\n",
    "Untracked files:\n",
    "  (use \"git add <file>...\" to include in what will be committed)\n",
    "\tclientes.csv\n",
    "\treporte.txt\n",
    "\n",
    "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n",
    "Dropped refs/stash@{0} (d6bdabdc6e995952513e4eb6fd3940823b248fdf)\n",
    "No stash entries found.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El primero funcionó y vació el cajón; el segundo no tiene de dónde sacar. Es\n",
    "la forma que tiene Git de decirte que ya recuperaste todo ✅"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**El cajón es para minutos y solo existe en tu máquina. Para algo que\n",
    "va a dormir ahí, mejor un commit.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué hace git stash?Guarda los cambios que tienes a medias en un cajón aparte y te deja la carpeta limpia. Sirve cuando tienes que cambiar de rama de golpe y no quieres hacer un commit a medio hacer.\n",
    "\n",
    "¿Cómo recupero lo que guardé con stash?Con git stash pop, que lo devuelve y lo saca del cajón. Con git stash apply lo devuelve y lo deja guardado también.\n",
    "\n",
    "¿Cuántas cosas puedo tener en el stash?Las que quieras, se apilan. git stash list te las enseña, y ahí empieza el problema: un stash de hace tres semanas ya nadie recuerda qué traía."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 8 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/guardar-a-medias/\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
}
