{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Reescribir la historia sin quemar al equipo\n",
    "\n",
    "Amend, rebase y la única regla que no se rompe\n",
    "\n",
    "Cuaderno de práctica del capítulo 27 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/reescribir-la-historia/\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": [
    "Este capítulo va con una advertencia por delante, y no es de las de adorno.\n",
    "Todo lo que hay aquí es seguro mientras la rama viva solo en tu máquina, y es\n",
    "un problema en cuanto la compartes 🚧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que de verdad pasa cuando reescribes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un commit es su contenido más su mensaje más su padre más quién y cuándo.\n",
    "Cambia cualquiera de esas cosas y el hash cambia, o sea que\n",
    "**no estás editando un commit, estás creando otro**.\n",
    "\n",
    "Los originales siguen ahí (en el reflog de 25),\n",
    "pero tu rama ya apunta a los nuevos. Si alguien más tenía los viejos, para Git\n",
    "sus commits y los tuyos no tienen nada que ver 💥"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Arreglar el último commit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El caso más común de todos: te comiste una palabra en el mensaje, o se te\n",
    "olvidó un archivo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "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 vetnas de Lima\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git commit -q --amend -m \"Primeras ventas de Lima\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Mensaje arreglado y **el hash cambió**. Míralo bien, porque ahí\n",
    "está todo el capítulo: no se corrigió el commit, se hizo otro 🔁"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Agregar un archivo olvidado"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'canal,monto\\nBodegas,4200\\n' > canales.csv\n",
    "git add canales.csv\n",
    "git commit -q --amend --no-edit\n",
    "git show --stat --oneline HEAD | head -5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El `--no-edit` mantiene el mensaje tal cual. Ahora el commit\n",
    "lleva los dos archivos, como si nunca hubiera pasado nada 🤫"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Varios commits a la vez"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para esto está el rebase interactivo. Normalmente abre un editor; aquí lo\n",
    "hacemos sin editor, que es lo mismo y se puede ejecutar:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"wip\"\n",
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"wip 2\"\n",
    "printf 'Trujillo,1450\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"wip 3\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres commits que no le dicen nada a nadie. Los juntamos en uno con\n",
    "mensaje decente:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git reset -q --soft HEAD~3\n",
    "git commit -q -m \"Entran las ventas de Arequipa, Cusco y Trujillo\"\n",
    "git log --oneline\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese `reset --soft` es la forma más simple de juntar commits: mueve\n",
    "la etiqueta tres atrás pero deja todos los cambios señalados, así que un commit\n",
    "nuevo los recoge todos. Es lo que hace `squash` por dentro 🧵"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cambiar el orden o borrar uno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para eso sí hace falta el rebase interactivo, que se lanza con\n",
    "`git rebase -i HEAD~3` y abre una lista como esta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "pick 8a2b19c Entran las ventas de Arequipa\n",
    "pick 3c1f80a Entran las ventas de Cusco\n",
    "pick 5d9c2f1 Entran las ventas de Trujillo\n",
    "\n",
    "# pick   = dejarlo como está\n",
    "# reword = cambiar el mensaje\n",
    "# squash = juntarlo con el de arriba\n",
    "# drop   = borrarlo\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cambias la primera palabra de cada línea, guardas y cierras. Git rehace la\n",
    "historia siguiendo tus instrucciones. Y si algo sale mal a mitad,\n",
    "`git rebase --abort` lo deja todo como estaba 🧯"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La regla"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**No reescribas historia que ya publicaste.** No porque Git no\n",
    "te deje, sino porque cada persona que tenga esos commits va a tener que\n",
    "arreglar su copia a mano.\n",
    "\n",
    "Si por lo que sea hay que hacerlo, se avisa antes y se usa\n",
    "`--force-with-lease` en vez de `--force`, que al menos se\n",
    "niega si alguien subió algo mientras tanto 🛑"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Tus commits tenían mensajes feos, los ordenas con un rebase interactivo y quedan preciosos. La rama ya estaba subida.\n",
    "\n",
    "```\n",
    "$ git rebase -i HEAD~3\n",
    "$ git push --force origin reporte-por-canal\n",
    "\n",
    "# en el chat, media hora despues:\n",
    "# \"me sale que mi rama diverge, que hago\"\n",
    "# \"a mi me aparecen los commits duplicados\"\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 `--amend` sobre un commit que ya habías subido. ¿Qué pasó?\n",
    "\n",
    "a) Nada, es el mismo commit corregido\n",
    "\n",
    "b) Ahora tu rama y la de allá tienen historias distintas\n",
    "\n",
    "c) GitHub lo actualiza solo al hacer push\n",
    "\n",
    "d) Se borró el commit anterior"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Arregla un mensaje mal escrito\n",
    "\n",
    "Crea el catálogo con un error de dedo y corrígelo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Agrega un archivo olvidado\n",
    "\n",
    "Métele el README al commit que ya hiciste."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Haz tres commits desordenados\n",
    "\n",
    "Los típicos \"wip\" de una tarde."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Júntalos en uno\n",
    "\n",
    "Con `reset --soft`, que es lo que hace squash\n",
    "por dentro."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Comprueba que no se perdió nada\n",
    "\n",
    "El contenido tiene que ser exactamente el mismo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Recupera los commits originales\n",
    "\n",
    "Reescribir no borra: el reflog sigue teniendo los viejos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Intenta enmendar sin tener commits\n",
    "\n",
    "Prueba `--amend` en un repositorio recién\n",
    "creado."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Reescribir crea commits nuevos con otro hash. Todo vale mientras la\n",
    "rama sea solo tuya.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 27 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/reescribir-la-historia/\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
}
