{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deshacer sin romper nada\n",
    "\n",
    "Restore, revert y reset, que suenan igual y hacen cosas muy distintas\n",
    "\n",
    "Cuaderno de práctica del capítulo 7 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/deshacer/\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: \"Y2l1ZGFkLG1vbnRvCkxpbWEsMTIwMApBcmVxdWlwYSw4OTA=\",\n",
    "    2: \"Pz8gY2xpZW50ZXMuY3N2\",\n",
    "    3: \"W21haW4gNTk3MmQ2YV0gUmV2ZXJ0ICJTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2xpZW50ZXMiCiBEYXRlOiBUaHUgSmFuIDE1IDA5OjAwOjAwIDIwMjYgLTA1MDAKIDEgZmlsZSBjaGFuZ2VkLCAyIGRlbGV0aW9ucygtKQogZGVsZXRlIG1vZGUgMTAwNjQ0IGNsaWVudGVzLmNzdgo1OTcyZDZhIFJldmVydCAiU2UgYWdyZWdhIGVsIGNhdGFsb2dvIGRlIGNsaWVudGVzIgplNGViODZiIFNlIGFncmVnYSBlbCBjYXRhbG9nbyBkZSBjbGllbnRlcwo1NzE4NzdiIFNlIGFncmVnYW4gbGFzIHZlbnRhcyBkZSBBcmVxdWlwYQo1NGRhNmUyIFByaW1lcmFzIHZlbnRhcyBkZSBMaW1h\",\n",
    "    4: \"dmVudGFzLmNzdg==\",\n",
    "    5: \"ZTRlYjg2YiBTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2xpZW50ZXMKNTcxODc3YiBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgQXJlcXVpcGEKNTRkYTZlMiBQcmltZXJhcyB2ZW50YXMgZGUgTGltYQpEICBjbGllbnRlcy5jc3Y=\",\n",
    "    6: \"SEVBRCBpcyBub3cgYXQgZTRlYjg2YiBTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2xpZW50ZXMKY2xpZW50ZXMuY3N2CnZlbnRhcy5jc3Y=\",\n",
    "    7: \"ZmF0YWw6IGJhZCByZXZpc2lvbiAnMDAwMDAwMCc=\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La tabla que quiero que te lleves"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Antes de nada, esto:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Quiero | Comando | ¿Destruye? |\n",
    "|---|---|---|\n",
    "| Tirar lo que edité y no guardé | `git restore archivo` | Sí, eso |\n",
    "| Sacar algo de la foto | `git restore --staged archivo` | No |\n",
    "| Anular un commit ya compartido | `git revert hash` | No |\n",
    "| Deshacer el último commit y quedarme los cambios | `git reset --soft HEAD~1` | No |\n",
    "| Borrar el último commit y todo lo que traía | `git reset --hard HEAD~1` | Sí, todo |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Guárdala. Yo la tuve pegada en la pantalla meses 📌"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preparo el terreno"
   ]
  },
  {
   "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",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Arequipa\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Revert, el que se puede usar sin miedo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`revert` no borra el commit: crea uno nuevo que hace justo lo\n",
    "contrario. La historia crece en vez de encogerse."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git revert --no-edit HEAD\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres commits, no uno. El de Arequipa sigue ahí y encima hay otro que lo\n",
    "deshace. Y el archivo quedó como estaba antes:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este es **el único que se puede usar cuando el commit ya lo tiene otra\n",
    "persona**, porque no cambia nada de lo que ya estaba. Los demás\n",
    "reescriben, y eso se cuenta en el capítulo 10."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reset soft, deshacer el commit y quedarte lo hecho"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reset --soft HEAD~1\n",
    "git log --oneline\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El commit del revert desapareció de la historia, pero su contenido se quedó\n",
    "en la foto, listo para volver a guardarse. Es lo que uso cuando hice un commit\n",
    "antes de tiempo o con el mensaje mal."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reset hard, el que sí borra"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git reset --hard HEAD\n",
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git reset --hard HEAD\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cusco no está. No se fue a ningún sitio recuperable: **nunca llegó a\n",
    "un commit**, así que Git no tiene de dónde sacarlo.\n",
    "\n",
    "Este es el único comando de todo el libro que destruye trabajo de verdad, y\n",
    "por eso el capítulo 8 existe: hay una forma de guardar lo\n",
    "que llevas antes de limpiar."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error de anular un commit que no existe"
   ]
  },
  {
   "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 revert --no-edit abc1234"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "fatal: bad revision 'abc1234'\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Bad revision*: ese hash no está en esta historia. Suele pasar cuando\n",
    "copias un hash de otra rama o de un mensaje viejo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Llevas dos horas con el análisis de las ventas por canal, se te enreda todo y decides empezar de nuevo desde el último commit.\n",
    "\n",
    "```\n",
    "$ git reset --hard HEAD\n",
    "\n",
    "HEAD is now at 8a2b19c Ventas por canal de Lima\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",
    "Subiste un commit que ya se llevaron dos compañeras y hay que anularlo. ¿Qué usas?\n",
    "\n",
    "a) `git reset --hard`\n",
    "\n",
    "b) `git revert`\n",
    "\n",
    "c) `git restore`\n",
    "\n",
    "d) Borrar el archivo y hacer un commit nuevo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Tira un cambio que no querías\n",
    "\n",
    "Escribe un monto mal en el CSV y descártalo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Saca algo de la foto sin perderlo\n",
    "\n",
    "Agrega un archivo de clientes, mételo en la foto y después\n",
    "sácalo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Un commit y su anulación\n",
    "\n",
    "Guarda el archivo de clientes y después anúlalo con revert."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Comprueba que el archivo se fue\n",
    "\n",
    "Mira qué hay en la carpeta después del revert."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Deshaz el commit pero quédate lo hecho\n",
    "\n",
    "Usa `--soft` sobre el revert y mira dónde quedan\n",
    "las cosas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Vuelve al último commit y limpia\n",
    "\n",
    "Descarta todo lo que hay pendiente con un reset duro."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Un hash inventado\n",
    "\n",
    "Intenta anular un commit que no existe."
   ]
  },
  {
   "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": [
    "**revert nunca destruye, reset --hard siempre puede. Si dudas, usa\n",
    "revert.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 7 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/deshacer/\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
}
