{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pedir ayuda sin quedarte esperando\n",
    "\n",
    "Qué es un issue, cómo se escribe uno que sí contestan y cómo se cierra desde un commit\n",
    "\n",
    "Cuaderno de soluciones del capítulo 21 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/issues/\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": [
    "Los issues son la parte de GitHub que menos usa quien está empezando y la\n",
    "que más rápido te desatasca. Es donde se pide ayuda, se reporta que algo no\n",
    "funciona y se discute qué hacer 💬\n",
    "\n",
    "Y antes de abrir uno, hay un paso que ahorra la mitad de las veces:\n",
    "**buscar**. Casi siempre alguien ya preguntó lo mismo, y en el\n",
    "hilo está la respuesta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué es y qué no"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un issue no es solo un error. En un proyecto sano hay de tres tipos:\n",
    "\n",
    "- **Algo está roto.** El clásico.\n",
    "\n",
    "- **Falta algo.** Una función, un dato, una parte del README.\n",
    "\n",
    "- **Una pregunta o una decisión.** \"¿Conviene separar el CSV por\n",
    "canal?\" es un issue perfectamente válido."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El issue que se contesta el mismo día"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cuatro bloques. Este es el molde que uso:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "Titulo: Error de codificacion al leer un CSV con tildes en Windows\n",
    "\n",
    "## Que hice\n",
    "python3 reporte.py ventas.csv\n",
    "\n",
    "## Que esperaba\n",
    "El total por ciudad\n",
    "\n",
    "## Que paso\n",
    "UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 34\n",
    "\n",
    "## Version\n",
    "reporte 1.2, Windows 11, Python 3.11\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fíjate en el título: no dice \"no funciona\", dice qué falla y dónde. Ese\n",
    "título es lo que hace que la siguiente persona con el mismo problema lo\n",
    "encuentre en vez de abrir otro igual 🔎"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El mensaje de error, copiado y no contado"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta es la parte donde más se pierde tiempo. \"Me sale un error de codificación\"\n",
    "no sirve; el error completo sí, porque dentro está el archivo, la línea y el\n",
    "byte exacto.\n",
    "\n",
    "Se copia de la terminal tal cual, y se pega entre tres tildes invertidas para\n",
    "que GitHub lo muestre como bloque:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "mkdir reporte-ventas\n",
    "cd reporte-ventas\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",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cat ventas-2019.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "cat: ventas-2019.csv: No such file or directory\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eso de ahí arriba, entero, es lo que va en el issue. Los cinco segundos de\n",
    "copiarlo te ahorran dos días de \"¿me pasas el error completo?\" ⏱️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los issues se cierran desde el commit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta es la parte que engancha a Git con GitHub. Si en el mensaje del commit\n",
    "escribes ciertas palabras seguidas del número, GitHub cierra el issue solo\n",
    "cuando ese commit llega a la rama principal."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Escribes | Qué hace |\n",
    "|---|---|\n",
    "| `Cierra #12` | Cierra el issue 12 al fusionar |\n",
    "| `Fixes #12` | Lo mismo, en inglés |\n",
    "| `Ver #12` | Lo enlaza sin cerrarlo |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Arequipa\n",
    "\n",
    "Faltaba la ciudad en el reporte por canal.\n",
    "\n",
    "Cierra #12\"\n",
    "git log -1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese cuerpo del commit, el que aprendiste a escribir en\n",
    "5, es donde va la referencia. Y así el historial queda\n",
    "enlazado con la conversación: dentro de un año, quien lea ese commit puede\n",
    "llegar al hilo donde se decidió 🔗"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Buscar entre los commits que cierran issues"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'Cusco,760\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Cusco\n",
    "\n",
    "Cierra #15\"\n",
    "git log --oneline --grep=\"Cierra #\"\n",
    "git log --grep=\"Cierra #12\" --format=\"%h %s\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese `--grep` del capítulo 6 aquí vale\n",
    "doble: te lleva del número del issue al cambio exacto que lo resolvió 🎯"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y una cosa de convivencia"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quien mantiene un proyecto abierto casi siempre lo hace gratis y en su\n",
    "tiempo libre. Un issue amable, con datos y sin urgencia fingida, se contesta.\n",
    "Uno que exige, no 🙂"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Una herramienta de IA que bajaste de GitHub no te funciona. Abres un issue para pedir ayuda.\n",
    "\n",
    "```\n",
    "Titulo: No funciona\n",
    "\n",
    "Hola, instale todo y me sale error. Alguien sabe que puede ser?\n",
    "Gracias\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "Ese issue no se puede contestar 🤷‍♀️\n",
    "\n",
    "Quien mantiene el proyecto no tiene tu computadora, ni tu versión, ni tu error. Con eso solo puede hacer una cosa: preguntarte todo otra vez, y ahí se van tres días de ida y vuelta.\n",
    "\n",
    "Un issue que se contesta el mismo día trae cuatro cosas: **qué hiciste, qué esperabas, qué pasó y el mensaje de error completo**, copiado tal cual y no descrito. Más la versión del programa y tu sistema.\n",
    "\n",
    "Y el título hace la mitad del trabajo. \"No funciona\" contra \"Error de codificación al leer un CSV con tildes en Windows\": el segundo lo encuentra alguien más con el mismo problema."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Vas a reportar que una herramienta falla. ¿Qué es lo más importante que pongas?\n",
    "\n",
    "a) El mensaje de error completo, copiado tal cual\n",
    "\n",
    "b) Una descripción detallada de lo frustrante que fue\n",
    "\n",
    "c) Una captura de pantalla de la terminal\n",
    "\n",
    "d) Cuántas veces lo intentaste\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Se entiende la frustración, pero no ayuda a nadie a encontrar la causa.\n",
    "\n",
    "*c)* Mejor que nada, pero no se puede buscar ni copiar. El texto sirve más.\n",
    "\n",
    "*d)* No cambia el diagnóstico. Lo que lo cambia es qué dice el error.\n",
    "\n",
    "El error copiado entero es la mitad de la respuesta 📋"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Reproduce un error para reportarlo\n",
    "\n",
    "Crea el proyecto de canales y provoca un error real para\n",
    "tener qué copiar."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ..\n",
    "mkdir canales\n",
    "cd canales\n",
    "git init -q\n",
    "printf 'canal,monto\\nBodegas,4200\\n' > canales.csv\n",
    "git add canales.csv\n",
    "git commit -q -m \"Ventas del canal bodegas\"\n",
    "git log --oneline\n",
    "5d7b179 Ventas del canal bodegas\n",
    "cat canales-2019.csv\n",
    "cat: canales-2019.csv: No such file or directory\n",
    "Eso, entero, es lo que va pegado en el issue."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Cierra un issue desde el commit\n",
    "\n",
    "Arregla algo y enlázalo con el issue 7."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'Horeca,3100\\n' >> canales.csv\n",
    "git add canales.csv\n",
    "git commit -q -m \"Se agrega el canal horeca\n",
    "\n",
    "Faltaba en el reporte mensual.\n",
    "\n",
    "Cierra #7\"\n",
    "git log -1 --format=\"%s%n%n%b\"\n",
    "Se agrega el canal horeca\n",
    "\n",
    "Faltaba en el reporte mensual.\n",
    "\n",
    "Cierra #7\n",
    "Al fusionar esto en la rama principal, GitHub cierra el issue 7 solo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Enlaza sin cerrar\n",
    "\n",
    "A veces un commit avanza en un issue pero no lo termina."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "printf 'Mayoristas,5600\\n' >> canales.csv\n",
    "git add canales.csv\n",
    "git commit -q -m \"Entra el canal mayorista\n",
    "\n",
    "Primer paso de #7, falta el de farmacias.\"\n",
    "git log -1 --format=\"%b\"\n",
    "Primer paso de #7, falta el de farmacias.\n",
    "Sin la palabra \"Cierra\", GitHub lo enlaza y lo deja abierto."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Busca qué commit resolvió un issue\n",
    "\n",
    "Del número del issue al cambio exacto."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git log --oneline --grep=\"#7\"\n",
    "6583f12 Entra el canal mayorista\n",
    "43158b0 Se agrega el canal horeca\n",
    "Dos commits mencionan el 7. El que lo cerró y el que avanzó en él."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Lista todos los cierres\n",
    "\n",
    "Un repaso rápido de qué se cerró en este proyecto."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git log --grep=\"Cierra #\" --format=\"%h %s\"\n",
    "43158b0 Se agrega el canal horeca\n",
    "Con un proyecto de meses, esta lista es medio informe de avance 📈"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Mira el commit entero antes de comentarlo\n",
    "\n",
    "Cuando contestas en un issue, conviene tener delante lo\n",
    "que se cambió."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git show --stat HEAD\n",
    "commit 6583f1222387a29de931c25a5323f09dff789888\n",
    "Author: Miss Yera <hola@missyera.com>\n",
    "Date:   Thu Jan 15 09:00:00 2026 -0500\n",
    "\n",
    "    Entra el canal mayorista\n",
    "    \n",
    "    Primer paso de #7, falta el de farmacias.\n",
    "\n",
    " canales.csv | 1 +\n",
    " 1 file changed, 1 insertion(+)\n",
    "Qué archivos y cuántas líneas, sin leer el diff completo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Comprueba tu plantilla de issue\n",
    "\n",
    "Los proyectos serios guardan la plantilla dentro del\n",
    "repositorio, para que nadie tenga que acordarse."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "mkdir -p .github/ISSUE_TEMPLATE\n",
    "cat > .github/ISSUE_TEMPLATE/error.md <<'FIN'\n",
    "## Que hice\n",
    "## Que esperaba\n",
    "## Que paso\n",
    "## Version\n",
    "FIN\n",
    "git add .github\n",
    "git commit -q -m \"Plantilla para reportar errores\"\n",
    "cat .github/ISSUE_TEMPLATE/error.md\n",
    "git ls-files\n",
    "## Que hice\n",
    "## Que esperaba\n",
    "## Que paso\n",
    "## Version\n",
    ".github/ISSUE_TEMPLATE/error.md\n",
    "canales.csv\n",
    "GitHub la muestra sola al abrir un issue nuevo. Es la forma de conseguir\n",
    "buenos reportes sin pedirlos 📝"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Qué hiciste, qué esperabas, qué pasó y el error copiado. Y\n",
    "`Cierra #12` en el commit para que se cierre solo.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 21 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/issues/\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
}
