{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mirar un repositorio y saber si sirve\n",
    "\n",
    "Cómo decidir en dos minutos si un proyecto está vivo o abandonado\n",
    "\n",
    "Cuaderno de práctica del capítulo 15 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/leer-un-repositorio/\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: \"ZTM5OWMwNyBFbnRyYW4gbG9zIG1heW9yaXN0YXMKOWM1YjhjMCBFbnRyYSBlbCBjYW5hbCBob3JlY2EKZDY5Zjk0ZiBFbnRyYW4gbGFzIGJvZGVnYXMKODJhZTc4YiBBcnJhbmNhIGVsIHJlcG9ydGUgcG9yIGNhbmFs\",\n",
    "    2: \"MjAyNi0wMS0xNQ==\",\n",
    "    3: \"\",\n",
    "    4: \"ICAgICAgNCAyMDI2LTAx\",\n",
    "    5: \"UkVBRE1FIHNpCmxpY2VuY2lhIG5v\",\n",
    "    6: \"bGltcGlv\",\n",
    "    7: \"ZmF0YWw6IHBhdGggJ3ZlbnRhcy0yMDE5LmNzdicgZG9lcyBub3QgZXhpc3QgaW4gJ0hFQUQn\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Buscas \"chatbot whatsapp python\" en GitHub y salen doscientos proyectos.\n",
    "Alguno tiene doce mil estrellas y se ve precioso. ¿Ese?\n",
    "\n",
    "Depende, y averiguarlo toma dos minutos. Este capítulo es esa revisión, que\n",
    "yo hago siempre antes de meter algo ajeno en un proyecto de cliente 🔍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Por qué las estrellas engañan"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una estrella en GitHub es un marcador: \"esto me interesa, lo guardo\". Se\n",
    "pone y casi nadie la quita. O sea que las estrellas miden **popularidad\n",
    "acumulada desde siempre**, no si el proyecto sigue vivo hoy.\n",
    "\n",
    "Lo mismo pasa con los forks: cuentan cuánta gente lo copió alguna vez, no\n",
    "cuánta lo usa."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Las cuatro señales que sí valen"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Señal | Buena | Para huir |\n",
    "|---|---|---|\n",
    "| Último commit | Semanas | Más de dos años |\n",
    "| Quién mantiene | Varias personas | Una sola y sin actividad |\n",
    "| Issues abiertos | Con respuesta del autor | Cientos sin contestar |\n",
    "| README y licencia | Los dos | Ninguno |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Vamos a sacar las tres primeras desde la terminal. Primero fabricamos un\n",
    "proyecto con historia para tener qué mirar:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir bot-ventas\n",
    "cd bot-ventas\n",
    "git init -q\n",
    "printf '# Bot de ventas\\n\\nResponde pedidos por WhatsApp.\\n' > README.md\n",
    "git add README.md\n",
    "git commit -q -m \"Primera version del bot de ventas\"\n",
    "printf 'MIT License\\n' > LICENSE\n",
    "git add LICENSE\n",
    "git commit -q -m \"Se agrega la licencia MIT\"\n",
    "printf 'ciudad,monto\\nLima,1200\\n' > ventas.csv\n",
    "git add ventas.csv\n",
    "GIT_AUTHOR_NAME=\"Rosa Quispe\" GIT_AUTHOR_EMAIL=\"rosa@ejemplo.com\" \\\n",
    "  git commit -q -m \"Entran las ventas de Lima\"\n",
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "GIT_AUTHOR_NAME=\"Rosa Quispe\" GIT_AUTHOR_EMAIL=\"rosa@ejemplo.com\" \\\n",
    "  git commit -q -m \"Entran las ventas de Arequipa\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Señal 1: cuándo se tocó por última vez"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log -1 --format=\"%ad\" --date=short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un solo dato y es el más importante de todos. Si esa fecha tiene más de dos\n",
    "años y el proyecto depende de librerías que cambian, ya sabes 📅\n",
    "\n",
    "Para verlo con más contexto, los últimos cinco con su fecha:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log -5 --format=\"%ad  %s\" --date=short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Señal 2: cuánta gente lo sostiene"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git shortlog -sn"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A la izquierda cuántos commits, a la derecha quién. Un proyecto con una sola\n",
    "persona no es malo, pero es frágil: si esa persona se cansa, se acabó. Esto se\n",
    "llama el *bus factor* y con uno solo conviene saberlo antes 🚌"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Señal 3: qué hay dentro"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "ls -a\n",
    "test -f README.md && echo \"tiene README\"\n",
    "test -f LICENSE && echo \"tiene licencia\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sin licencia, el proyecto es de su autor y punto. Lo vemos en el capítulo\n",
    "16, porque tiene más consecuencias de las que parece."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Señal 4: los issues"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Esta no sale por terminal, porque los issues viven en GitHub y no en Git.\n",
    "Pero es la que más me dice: entra a la pestaña **Issues**, ordena\n",
    "por más recientes y mira si el autor contesta. Un proyecto con trescientos\n",
    "issues abiertos y ninguna respuesta en un año está abandonado aunque el código\n",
    "se vea impecable.\n",
    "\n",
    "Mismo truco en **Pull requests**: si hay veinte propuestas de\n",
    "gente esperando desde hace meses, nadie está al volante 🛞"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El resumen de dos minutos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "echo \"== ultimo commit ==\" && git log -1 --format=\"%ad  %s\" --date=short\n",
    "echo \"== gente ==\" && git shortlog -sn | head -3\n",
    "echo \"== archivos clave ==\" && ls | head -5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eso, pegado en la terminal después de clonar, resuelve la decisión casi\n",
    "siempre 🧾"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Buscas una librería para conectar tu bot de WhatsApp, encuentras una con muchísimas estrellas y la instalas sin dudar.\n",
    "\n",
    "```\n",
    "$ git log -1 --format=\"%ad\" --date=short\n",
    "2019-03-11\n",
    "\n",
    "$ ls\n",
    "README.md  setup.py  whatsapp_bot\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",
    "Dos librerías hacen lo mismo. Una tiene 12.000 estrellas y último commit de 2019. La otra tiene 300 y último commit de la semana pasada. ¿Cuál usas?\n",
    "\n",
    "a) La de 12.000, es la que usa todo el mundo\n",
    "\n",
    "b) La de 300, que sigue viva\n",
    "\n",
    "c) La que tenga mejor README\n",
    "\n",
    "d) Ninguna, mejor lo hago yo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Arma un proyecto con historia\n",
    "\n",
    "Crea el repositorio del reporte de canales con cuatro\n",
    "commits de dos personas distintas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Saca la fecha del último commit\n",
    "\n",
    "La señal número uno, en una línea."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Cuenta quién sostiene el proyecto\n",
    "\n",
    "Lista los autores ordenados por cantidad de commits."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Mira el ritmo por mes\n",
    "\n",
    "Agrupa los commits por mes para ver si el proyecto se\n",
    "mueve o solo tuvo un arranque."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Comprueba los archivos clave\n",
    "\n",
    "Mira si tiene README y licencia."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Busca claves olvidadas dentro\n",
    "\n",
    "Antes de confiar en un proyecto ajeno, revisa que no\n",
    "traiga secretos publicados por descuido."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Pide la revisión de un archivo que no existe\n",
    "\n",
    "Prueba a mirar la historia de un archivo que el proyecto\n",
    "no tiene."
   ]
  },
  {
   "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": [
    "**Las estrellas cuentan el pasado. La fecha del último commit y quién\n",
    "contesta los issues cuentan el presente.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 15 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/leer-un-repositorio/\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
}
