{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Bajar un proyecto y hacerlo funcionar\n",
    "\n",
    "El botón verde, git clone y qué hacer con lo que descargaste\n",
    "\n",
    "Cuaderno de soluciones del capítulo 14 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/clonar-un-proyecto/\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": [
    "Este es el capítulo que pidió aquella persona en LinkedIn: *\"he visto\n",
    "varios desarrollos compartidos allí pero todavía me cuesta entender cómo\n",
    "instalarlos\"*.\n",
    "\n",
    "Y tiene toda la razón en que cuesta, porque en GitHub hay un botón verde\n",
    "grande que dice **Code** y lo que ofrece primero es justo lo que\n",
    "menos conviene 🟢"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El botón verde por dentro"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Al pulsarlo salen cuatro opciones. Traducidas:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Opción | Qué te llevas | ¿Se puede actualizar? |\n",
    "|---|---|---|\n",
    "| HTTPS | Todo, con historia | Sí, con `git pull` |\n",
    "| SSH | Todo, con historia | Sí, y sin pedir nada |\n",
    "| GitHub CLI | Todo, pero necesita otro programa | Sí |\n",
    "| Download ZIP | Los archivos de hoy | No |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "La regla es fácil: si vas a usar el proyecto, clona. El ZIP es para\n",
    "curiosear un rato y borrar."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Clonar de verdad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Para verlo funcionando sin depender de internet, primero fabricamos un\n",
    "proyecto y lo dejamos en un servidor de práctica, como en el capítulo\n",
    "12. Ese va a hacer de \"proyecto que encontraste\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "mkdir analisis-ventas\n",
    "cd analisis-ventas\n",
    "git init -q\n",
    "printf 'ciudad,monto\\nLima,1200\\nArequipa,890\\nCusco,760\\n' > ventas.csv\n",
    "printf '# Analisis de ventas\\n\\nCalcula el total por ciudad.\\n' > README.md\n",
    "printf 'pandas\\n' > requirements.txt\n",
    "printf 'import pandas as pd\\nprint(pd.read_csv(\"ventas.csv\")[\"monto\"].sum())\\n' > total.py\n",
    "git add .\n",
    "git commit -q -m \"Primera version del analisis de ventas\"\n",
    "cd ..\n",
    "git clone -q --bare analisis-ventas servidor.git\n",
    "echo \"proyecto publicado en servidor.git\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora hazte la idea de que `servidor.git` es una dirección de\n",
    "GitHub que te pasó alguien. Bajarlo es una línea:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git clone servidor.git mi-copia\n",
    "cd mi-copia\n",
    "ls"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahí está todo. Y fíjate en el detalle que lo cambia todo: te trajiste la\n",
    "historia entera, no la foto de hoy."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git log --oneline\n",
    "git remote -v"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El remoto quedó apuntado solo. `clone` hace tres cosas de un\n",
    "tirón: crea la carpeta, copia el repositorio y configura `origin` 📦"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dónde cae la carpeta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`git clone` crea la carpeta **dentro de donde estés\n",
    "parada**. Si estabas en tu carpeta personal, ahí te la deja. Es el\n",
    "motivo número uno de \"clone el proyecto y no lo encuentro\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pwd\n",
    "cd ..\n",
    "mkdir -p proyectos\n",
    "cd proyectos\n",
    "git clone -q ../servidor.git ventas\n",
    "ls\n",
    "pwd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese nombre del final es opcional: sin él, la carpeta se llama como el\n",
    "proyecto. Con él, como tú quieras 📁"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Los dos pasos que Git no hace"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Clonar te da los archivos. No te da el programa funcionando, y aquí es donde\n",
    "la gente se queda mirando la pantalla.\n",
    "\n",
    "**Paso uno: leer el README.** Siempre. Es el archivo que explica\n",
    "qué es esto y cómo se pone en marcha."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ventas\n",
    "cat README.md\n",
    "cat requirements.txt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Paso dos: instalar lo que pide.** Casi ningún proyecto se\n",
    "ejecuta tal cual: necesita librerías. El archivo que las lista se llama\n",
    "`requirements.txt` en Python, `package.json` en\n",
    "JavaScript, y siempre está en la raíz.\n",
    "\n",
    "En Python son dos líneas, y la primera es la que casi todo el mundo se salta:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "python3 -m venv .venv          # una caja aparte para este proyecto\n",
    "source .venv/bin/activate      # entrar a la caja\n",
    "pip install -r requirements.txt\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese entorno virtual evita que las librerías de un proyecto se peleen con las\n",
    "de otro. Si nunca lo has hecho, está explicado con calma en\n",
    "[Python desde cero](https://missyera.com/guias/python-desde-cero/) 🐍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Actualizar cuando saquen algo nuevo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Aquí se ve por qué el ZIP no servía. Alguien mejora el proyecto original:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ../../analisis-ventas\n",
    "printf 'Trujillo,1450\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Entran las ventas de Trujillo\"\n",
    "git push -q ../servidor.git main\n",
    "echo \"cambio publicado\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y tú, en tu copia, te lo traes con una palabra:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ../proyectos/ventas\n",
    "git pull -q origin main\n",
    "cat ventas.csv\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Trujillo apareció y la historia creció. Con un ZIP habrías tenido que\n",
    "descargar otro, descomprimirlo y comparar carpetas a mano 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Encuentras en GitHub una herramienta de IA que quieres probar, le das al botón verde, descargas el ZIP y lo descomprimes en tu escritorio.\n",
    "\n",
    "```\n",
    "$ cd ~/Escritorio/herramienta-main\n",
    "$ ls -a\n",
    ".  ..  README.md  requirements.txt  src\n",
    "\n",
    "$ git pull\n",
    "fatal: not a git repository (or any of the parent directories): .git\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "El ZIP viene sin historia y sin conexión 📦\n",
    "\n",
    "Descargar el ZIP te da los archivos de hoy y nada más: no hay `.git`, así que no puedes actualizar, no puedes ver qué cambió ni volver a la versión de antes. Cuando la herramienta saque una versión nueva, te toca descargar otro ZIP y comparar carpetas a mano.\n",
    "\n",
    "Con `git clone` te llevas lo mismo **más la historia y más el enlace al original**, y actualizar es escribir `git pull`.\n",
    "\n",
    "El ZIP sirve para una cosa: mirar por encima un proyecto que no piensas usar. Para todo lo demás, clonar."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Clonaste una herramienta hace un mes y hoy sacaron una versión nueva. ¿Qué haces?\n",
    "\n",
    "a) Borro la carpeta y clono otra vez\n",
    "\n",
    "b) `git pull` dentro de la carpeta\n",
    "\n",
    "c) Descargo el ZIP nuevo y reemplazo los archivos\n",
    "\n",
    "d) `git clone` otra vez encima\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la b.**\n",
    "\n",
    "*a)* Funciona, pero pierdes cualquier cambio tuyo y bajas todo de nuevo sin necesidad.\n",
    "\n",
    "*c)* Es justo el trabajo manual que clonar te ahorra, y encima pisa lo que hayas tocado.\n",
    "\n",
    "*d)* Git no deja clonar sobre una carpeta que ya existe, y no haría falta aunque dejara.\n",
    "\n",
    "Clonar es una vez; actualizar es `git pull` 🔄"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Publica un proyecto de práctica\n",
    "\n",
    "Arma el catálogo de clientes y déjalo en un servidor\n",
    "local, que hará de GitHub."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ~\n",
    "mkdir catalogo-clientes\n",
    "cd catalogo-clientes\n",
    "git init -q\n",
    "printf 'cliente,ciudad,canal\\nBodega Inti,Cusco,Bodegas\\n' > clientes.csv\n",
    "printf '# Catalogo de clientes\\n\\nUn CSV por canal.\\n' > README.md\n",
    "git add .\n",
    "git commit -q -m \"Catalogo inicial de clientes\"\n",
    "cd ..\n",
    "git clone -q --bare catalogo-clientes clientes-servidor.git\n",
    "echo \"publicado\"\n",
    "publicado\n",
    "Ese `--bare` es lo que guarda GitHub: la historia sin archivos a\n",
    "la vista."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Clónalo\n",
    "\n",
    "Bájalo como si lo hubieras encontrado, con el nombre\n",
    "`clientes`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git clone clientes-servidor.git clientes\n",
    "cd clientes\n",
    "ls\n",
    "Cloning into 'clientes'...\n",
    "done.\n",
    "README.md\n",
    "clientes.csv\n",
    "Los mismos archivos, en una carpeta nueva y con nombre tuyo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Comprueba que trajiste la historia\n",
    "\n",
    "Mira el log y el remoto de la copia."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "git log --oneline\n",
    "git remote -v\n",
    "fc01d00 Catalogo inicial de clientes\n",
    "origin\t/home/miss-yera/clientes-servidor.git (fetch)\n",
    "origin\t/home/miss-yera/clientes-servidor.git (push)\n",
    "El commit original está entero y `origin` quedó configurado\n",
    "solo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Lee antes de tocar\n",
    "\n",
    "Abre el README, que es siempre el primer paso."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cat README.md\n",
    "# Catalogo de clientes\n",
    "\n",
    "Un CSV por canal.\n",
    "Cuando un proyecto no tiene README, eso ya es información sobre el\n",
    "proyecto 👀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Trae una mejora del original\n",
    "\n",
    "Agrega un mayorista de Piura en el proyecto original,\n",
    "publícalo y bájalo en tu copia."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ../catalogo-clientes\n",
    "printf 'Mayorista Norte,Piura,Mayoristas\\n' >> clientes.csv\n",
    "git add clientes.csv\n",
    "git commit -q -m \"Entra el mayorista de Piura\"\n",
    "git push -q ../clientes-servidor.git main\n",
    "cd ../clientes\n",
    "git pull -q origin main\n",
    "cat clientes.csv\n",
    "cliente,ciudad,canal\n",
    "Bodega Inti,Cusco,Bodegas\n",
    "Mayorista Norte,Piura,Mayoristas\n",
    "Una palabra y ya estás al día 🔄"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Clona solo lo último\n",
    "\n",
    "Cuando un proyecto tiene años de historia y solo quieres\n",
    "usarlo, se puede bajar sin el pasado con `--depth 1`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ..\n",
    "git clone -q --depth 1 clientes-servidor.git clientes-ligero\n",
    "cd clientes-ligero\n",
    "git log --oneline\n",
    "warning: --depth is ignored in local clones; use file:// instead.\n",
    "68b5ac0 Entra el mayorista de Piura\n",
    "fc01d00 Catalogo inicial de clientes\n",
    "Un solo commit en vez de la historia entera. Con proyectos grandes es la\n",
    "diferencia entre segundos y minutos ⚡"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Clona en una carpeta que ya existe\n",
    "\n",
    "Prueba a clonar encima de una carpeta con cosas dentro y\n",
    "mira qué dice."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cd ..\n",
    "mkdir ocupada\n",
    "printf 'algo\\n' > ocupada/notas.txt\n",
    "git clone clientes-servidor.git ocupada\n",
    "fatal: destination path 'ocupada' already exists and is not an empty directory.\n",
    "Git se niega antes de tocar nada. Es de los errores amables: te protege de\n",
    "pisar tu propio trabajo 🛡️"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Clonar trae los archivos, la historia y el enlace al original. El\n",
    "ZIP solo trae los archivos de hoy.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 14 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/clonar-un-proyecto/\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
}
