{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Escribir commits para tu yo del futuro\n",
    "\n",
    "Qué poner en el mensaje y cómo arreglar el último cuando sale mal\n",
    "\n",
    "Cuaderno de práctica del capítulo 5 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/hacer-commits/\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: \"U2UgYWdyZWdhIGVsIGNhdGFsb2dvIGRlIGNhbmFsZXMKClBvciBhaG9yYSBzb2xvIGJvZGVnYS4gTWluaW1hcmtldCB5IGhvcmVjYSBlbnRyYW4gY3VhbmRvIGVsIGFyZWEgY29tZXJjaWFsIGNvbmZpcm1lIGxvcyBub21icmVzLg==\",\n",
    "    2: \"NGI5ODY3ZiBTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2FuYWxlcyBkZSB2ZW50YQ==\",\n",
    "    3: \"MGU2OTBmMSBTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2FuYWxlcyBkZSB2ZW50YQogY2FuYWxlcy5jc3YgIHwgMiArKwogY2xpZW50ZXMuY3N2IHwgMiArKwogdmVudGFzLmNzdiAgIHwgMSArCiAzIGZpbGVzIGNoYW5nZWQsIDUgaW5zZXJ0aW9ucygrKQ==\",\n",
    "    4: \"NA==\",\n",
    "    5: \"OTJjMzAyNSBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgQXJlcXVpcGEgZGVsIGNpZXJyZSBkZSBtZXM=\",\n",
    "    6: \"MGU2OTBmMSAgU2UgYWdyZWdhIGVsIGNhdGFsb2dvIGRlIGNhbmFsZXMgZGUgdmVudGEKZjJkMTFmNyAgU2UgYWdyZWdhbiBsYXMgdmVudGFzIGRlIFRydWppbGxvIGRlbCBjaWVycmUgZGUgbWVzCjkyYzMwMjUgIFNlIGFncmVnYW4gbGFzIHZlbnRhcyBkZSBBcmVxdWlwYSBkZWwgY2llcnJlIGRlIG1lcwplZGYyNGViICBjYW1iaW9z\",\n",
    "    7: \"QWJvcnRpbmcgY29tbWl0IGR1ZSB0byBlbXB0eSBjb21taXQgbWVzc2FnZS4=\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El mensaje es la mitad del commit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El commit guarda el qué. El mensaje guarda el **por qué**, y esa\n",
    "es la parte que ningún programa puede reconstruir después.\n",
    "\n",
    "Armo el repositorio de la tienda y hago dos commits, uno con un mensaje malo\n",
    "y otro con uno bueno, para que veas la diferencia en la historia:"
   ]
  },
  {
   "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 \"cambios\"\n",
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Arequipa del cierre de mes\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dentro de seis meses el primero no te dice nada. El segundo te dice qué\n",
    "buscar sin abrir un archivo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La regla que uso"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres cosas y ya está:\n",
    "\n",
    "- **Qué pasó, no qué tocaste.** \"Se corrige el IGV del reporte\",\n",
    "no \"modificado reporte.py\".\n",
    "\n",
    "- **Una idea por commit.** Si tienes que escribir \"y\" en el\n",
    "mensaje, probablemente son dos commits.\n",
    "\n",
    "- **Que se entienda solo.** Sin \"lo de ayer\" ni \"el arreglo que\n",
    "hablamos\", porque en seis meses eso no existe."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cuando el mensaje no cabe en una línea"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para lo complicado, un commit puede tener título y explicación. Se pasan dos\n",
    "`-m` y el segundo es el cuerpo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'Trujillo,1450\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Trujillo\" \\\n",
    "  -m \"Llegaron por WhatsApp del jefe de bodega y no por el sistema, asi que el monto esta sin IGV.\"\n",
    "git log -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El título es lo que se lee en la lista; el cuerpo lo lee quien necesita el\n",
    "detalle. Ahí es donde se escribe lo que no se puede deducir mirando el código 📝"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Arreglar el último commit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Te equivocaste en el mensaje o se te olvidó un archivo. Mientras\n",
    "**no lo hayas compartido**, el último commit se puede rehacer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git commit -q --amend -m \"Se agregan las ventas de Trujillo del cierre de mes\"\n",
    "git log --oneline -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fíjate en algo importante: **el hash cambió**. No corrigió el\n",
    "commit, hizo uno nuevo y tiró el viejo. Por eso la regla del \"mientras no lo\n",
    "hayas compartido\", que retomamos en el capítulo 10 cuando entren\n",
    "otras personas al proyecto."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El commit sin mensaje"
   ]
  },
  {
   "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",
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -m \"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "Aborting commit due to empty commit message.\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Git se niega. Es de las pocas veces que un programa te obliga a explicarte, y\n",
    "la verdad es que hace bien 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Vas a cerrar el día y guardas todo lo que tocaste desde la mañana en un solo commit, que es lo cómodo.\n",
    "\n",
    "```\n",
    "$ git add .\n",
    "$ git commit -m \"Avances del dia\"\n",
    "\n",
    "[main 5d9c2f1] Avances del dia\n",
    " 9 files changed, 340 insertions(+), 88 deletions(-)\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",
    "¿Cuál de estos mensajes sirve dentro de seis meses?\n",
    "\n",
    "a) actualización\n",
    "\n",
    "b) Se corrige el IGV mal calculado en el reporte de ventas\n",
    "\n",
    "c) arreglos varios\n",
    "\n",
    "d) cambios en ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Un commit con título y cuerpo\n",
    "\n",
    "Agrega el canal de cada venta y explica en el cuerpo de\n",
    "dónde salió el dato."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Corrige el mensaje del último\n",
    "\n",
    "Cámbiale el título al commit que acabas de hacer y\n",
    "comprueba que el hash es otro."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Mete un archivo que se te olvidó\n",
    "\n",
    "`--amend` no sirve solo para el mensaje. Agrega\n",
    "un archivo al último commit sin crear uno nuevo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Cuenta cuántos commits llevas\n",
    "\n",
    "Pide el número total de la historia."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Busca un commit por su mensaje\n",
    "\n",
    "Encuentra los commits que hablen de Arequipa."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Los mensajes a tu manera\n",
    "\n",
    "Muestra la historia con el formato que tú elijas: hash\n",
    "corto, mensaje y hace cuánto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. El commit que Git no deja hacer\n",
    "\n",
    "Intenta guardar con un mensaje vacío."
   ]
  },
  {
   "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": [
    "**El mensaje lo escribes para quien va a leerlo dentro de seis meses,\n",
    "y esa persona eres tú.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntas frecuentes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "¿Qué es un commit en Git?Una foto de tus archivos en un momento, con un mensaje que dice qué cambió y por qué. La historia del proyecto es la fila de esas fotos.\n",
    "\n",
    "¿Cómo se hace un commit?Primero git add para elegir qué entra, después git commit con el mensaje. Son dos pasos a propósito: no todo lo que tocaste tiene que entrar junto.\n",
    "\n",
    "¿Cómo se escribe un buen mensaje de commit?Que diga qué cambia y por qué, no qué archivos tocaste. \"Arregla el total que salía sin IGV\" sirve; \"cambios\" no sirve para nada.\n",
    "\n",
    "¿Cómo deshago el último commit?Depende de si ya lo subiste. Si no, git reset lo deshace. Si sí, git revert crea un commit que lo anula, que es lo correcto porque no reescribe historia que ya vio otra gente."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 5 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/hacer-commits/\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
}
