{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Por qué tu repositorio pesa quinientos megas\n",
    "\n",
    "El .gitignore, y por qué no saca lo que ya estaba dentro\n",
    "\n",
    "Cuaderno de práctica del capítulo 9 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/ignorar-archivos/\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: \"IE0gLmdpdGlnbm9yZQ==\",\n",
    "    2: \"IE0gLmdpdGlnbm9yZQo/PyB2ZW50YXMubG9n\",\n",
    "    3: \"LmdpdGlnbm9yZTo1OioubG9nCXBlZGlkb3MubG9n\",\n",
    "    4: \"LmdpdGlnbm9yZQp2ZW50YXMuY3N2\",\n",
    "    5: \"LmdpdGlnbm9yZQp2ZW50YXMuY3N2CmJhc3VyYS50bXA=\",\n",
    "    6: \"Mg==\",\n",
    "    7: \"\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Qué nunca debe entrar a un repositorio"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres familias, y las tres por motivos distintos:\n",
    "\n",
    "- **Lo que tiene secretos.** Archivos `.env`, claves,\n",
    "contraseñas. Este es el peligroso.\n",
    "\n",
    "- **Lo que se genera solo.** Carpetas de dependencias, archivos\n",
    "compilados, cachés. Ocupan muchísimo y se vuelven a crear en un comando.\n",
    "\n",
    "- **Lo que es tuyo y de nadie más.** La configuración de tu\n",
    "editor, archivos temporales del sistema."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cómo se escribe la lista"
   ]
  },
  {
   "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",
    "mkdir cache\n",
    "printf 'basura\\n' > cache/temporal.txt\n",
    "printf 'CLAVE=secreta123\\n' > .env\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí están los tres, y el `.env` con la clave a un\n",
    "`git add .` de irse a internet. Escribo la lista:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf '.env\\ncache/\\n*.log\\n' > .gitignore\n",
    "cat .gitignore\n",
    "git status --short"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Desaparecieron. Ahora Git solo ve `ventas.csv` y el propio\n",
    "`.gitignore`, que sí se versiona porque el equipo entero tiene que\n",
    "compartir la misma lista."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los cuatro patrones que uso"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `.env`, un archivo con ese nombre exacto.\n",
    "\n",
    "- `cache/`, la carpeta entera con lo que tenga dentro.\n",
    "\n",
    "- `*.log`, todo lo que termine así.\n",
    "\n",
    "- `!importante.log`, la excepción: esto sí entra aunque el patrón\n",
    "de arriba lo excluya."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preguntar por qué se ignora algo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git add ventas.csv .gitignore\n",
    "git commit -q -m \"Primeras ventas y la lista de ignorados\"\n",
    "git check-ignore -v cache/temporal.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Te dice qué archivo y qué línea lo está ignorando. Cuando un archivo no\n",
    "aparece y no entiendes por qué, este comando lo resuelve en un segundo 🔎"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y aquí viene lo importante"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Meto una carpeta pesada al repositorio, como si no me hubiera dado cuenta:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir librerias\n",
    "printf 'un archivo enorme\\n' > librerias/todo.js\n",
    "git add librerias\n",
    "git commit -q -m \"Se sube la carpeta de librerias sin querer\"\n",
    "git ls-files"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora la agrego a la lista y miro qué pasa:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'librerias/\\n' >> .gitignore\n",
    "git add .gitignore\n",
    "git commit -q -m \"Se ignora la carpeta de librerias\"\n",
    "git status --short\n",
    "git ls-files"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El estado dice que todo está limpio, así que parece que funcionó. Pero\n",
    "`git ls-files`, que lista lo que Git está siguiendo,\n",
    "**sigue teniendo el archivo dentro**.\n",
    "\n",
    "Eso es exactamente lo que pasó en el repositorio de missyera.com:\n",
    "`node_modules` y `staticfiles` llevaban meses en el\n",
    "`.gitignore` y a la vez dentro. Eran 1.964 archivos y 18,6 MB que el\n",
    "servidor se bajaba en cada despliegue y no usaba nunca."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sacar lo que ya entró"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git rm -r --cached -q librerias\n",
    "git commit -q -m \"Se saca la carpeta de librerias del repositorio\"\n",
    "git ls-files\n",
    "ls librerias"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Fuera del repositorio y **sigue en tu disco**. Eso es lo que\n",
    "significa `--cached`: deja de versionarlo, no lo borra 🎯"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error de preguntar por algo que no se ignora"
   ]
  },
  {
   "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 check-ignore -v ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ni una palabra, y sin embargo falló: no imprime nada y devuelve un código de\n",
    "error, que es como Git dice \"ese archivo no está ignorado por nadie\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Tu repositorio pesa 400 MB y tarda una eternidad en subir. Te das cuenta de que hay carpetas enormes que no deberían estar, las pones en el `.gitignore` y respiras tranquila.\n",
    "\n",
    "```\n",
    "$ echo \"node_modules/\" >> .gitignore\n",
    "$ git add .gitignore\n",
    "$ git commit -m \"Se ignora node_modules\"\n",
    "$ git status\n",
    "\n",
    "On branch main\n",
    "nothing to commit, working tree clean\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 sin querer un archivo con claves hace tres commits. ¿Qué haces primero?\n",
    "\n",
    "a) Lo agrego al `.gitignore`\n",
    "\n",
    "b) Cambio la clave en el proveedor\n",
    "\n",
    "c) Borro el archivo y hago un commit\n",
    "\n",
    "d) Uso `git rm --cached`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Ignora por extensión\n",
    "\n",
    "Crea dos archivos de registro y haz que Git ignore todos\n",
    "los que terminen en `.log`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. La excepción a la regla\n",
    "\n",
    "Haz que uno de esos registros sí entre, con la\n",
    "admiración."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Pregunta quién ignora qué\n",
    "\n",
    "Averigua qué línea del archivo está ignorando\n",
    "`pedidos.log`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Lista todo lo que Git está siguiendo\n",
    "\n",
    "Pide los archivos versionados, que no es lo mismo que los\n",
    "archivos que hay."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Mete algo que no debía y sácalo\n",
    "\n",
    "Versiona un archivo de caché y después quítalo sin borrarlo\n",
    "del disco."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Cuánto pesa lo que estás versionando\n",
    "\n",
    "Cuenta cuántos archivos sigue Git en este repositorio."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Un archivo que nadie ignora\n",
    "\n",
    "Pregunta por el CSV de ventas, que sí tiene que entrar."
   ]
  },
  {
   "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": [
    "**El .gitignore solo vale para lo que Git todavía no conoce. Lo que ya\n",
    "entró se saca con git rm --cached.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 9 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/ignorar-archivos/\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
}
