{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Trabajar sin pisarse\n",
    "\n",
    "Fetch, pull y la rutina que evita el 99% de los líos de equipo\n",
    "\n",
    "Cuaderno de soluciones del capítulo 22 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/trabajar-sin-pisarse/\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": [
    "## 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({}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Trabajar sola con Git es fácil. Los problemas empiezan cuando hay dos\n",
    "personas tocando el mismo proyecto, y casi todos vienen de lo mismo: alguien\n",
    "trabajó cuatro días sin bajar lo de los demás 🙃"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fetch y pull, que no son sinónimos"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "|  | `git fetch` | `git pull` |\n",
    "|---|---|---|\n",
    "| Trae lo de allá | Sí | Sí |\n",
    "| Toca tus archivos | No | Sí |\n",
    "| Puede dar conflicto | No | Sí |\n",
    "| Cuándo lo uso | Para mirar antes de decidir | Cuando quiero ponerme al día |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En una frase: **`pull` es `fetch` más\n",
    "`merge`**. Y como el merge es la parte que puede doler,\n",
    "`fetch` primero te deja mirar sin compromiso 👀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Mirar antes de mezclar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Montamos un proyecto con dos personas trabajando:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "mkdir equipo\n",
    "cd equipo\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",
    "cd ..\n",
    "git clone -q --bare equipo servidor.git\n",
    "cd equipo\n",
    "git remote add origin ../servidor.git\n",
    "git push -q -u origin main\n",
    "cd ..\n",
    "git clone -q servidor.git compañera\n",
    "cd compañera\n",
    "printf 'canal,monto\\nBodegas,4200\\n' > canales.csv\n",
    "git add canales.csv\n",
    "git commit -q -m \"Entra el reporte por canal\"\n",
    "git push -q origin main\n",
    "cd ../equipo\n",
    "git fetch -q origin\n",
    "git status --short --branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese `behind 1` es la información que da `fetch`:\n",
    "*\"allá hay un commit que tú no tienes\"*. Tus archivos siguen intactos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log --oneline HEAD..origin/main\n",
    "git diff --stat HEAD origin/main"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ahora sabes exactamente qué te vas a traer antes de traértelo. Esto es lo\n",
    "que yo hago siempre antes de un pull en un proyecto con gente 🔍"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Y ahora sí, ponerse al día"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git merge -q origin/main\n",
    "ls\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eso, `fetch` y luego `merge`, es literalmente lo mismo\n",
    "que hace `git pull`. Con la ventaja de que miraste en medio."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## La rutina de cada mañana"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tres líneas, y son las que evitan casi todo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q main\n",
    "git pull -q --no-rebase origin main\n",
    "git switch -q -c reporte-por-ciudad\n",
    "git status --short --branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ponerte al día, y recién ahí crear tu rama del día. Si empiezas a trabajar\n",
    "sin bajar, tu rama nace de una versión vieja y el conflicto está garantizado\n",
    "para el viernes 📅"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cuando el pull se niega"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este mensaje asusta y es de los buenos:"
   ]
  },
  {
   "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 switch -q main\n",
    "printf 'ciudad,monto\\nLima,1200\\nArequipa,890\\nCusco,760\\nTrujillo,1450\\nPiura,980\\n' > ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Entra el resto de ciudades\"\n",
    "git push -q origin main\n",
    "cd ../compañera\n",
    "git pull -q --no-rebase origin main\n",
    "sed -i 's/Lima,1200/Lima,1290/' ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se corrige el monto de Lima\"\n",
    "git push -q origin main\n",
    "cd ../equipo\n",
    "printf 'Chiclayo,1120\\n' >> ventas.csv\n",
    "git pull --no-rebase origin main"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "From ../servidor\n",
    " * branch            main       -> FETCH_HEAD\n",
    "   50d9fc5..dde8c21  main       -> origin/main\n",
    "error: Your local changes to the following files would be overwritten by merge:\n",
    "\tventas.csv\n",
    "Please commit your changes or stash them before you merge.\n",
    "Aborting\n",
    "Updating 50d9fc5..dde8c21\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Git no pisó tu trabajo. Te está diciendo *\"tienes cambios sin guardar en\n",
    "un archivo que voy a tocar, decide tú\"*. Las dos salidas son de capítulos\n",
    "anteriores: commit, o cajón con 8 🧰"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git stash push -q -m \"Chiclayo a medias\"\n",
    "git pull -q --no-rebase origin main\n",
    "git stash pop\n",
    "cat ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El monto corregido de Lima entró y Chiclayo volvió encima. Nadie perdió\n",
    "nada 🤝"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Llevas la mañana con el reporte de canales a medias. Antes de almorzar traes lo que subió el equipo.\n",
    "\n",
    "```\n",
    "$ git status --short\n",
    " M canales.csv\n",
    "\n",
    "$ git pull\n",
    "error: Your local changes to the following files would be overwritten by merge:\n",
    "\tcanales.csv\n",
    "Please commit your changes or stash them before you merge.\n",
    "Aborting\n",
    "```\n",
    "\n",
    "**Qué está mal**\n",
    "\n",
    "Git te frenó, y menos mal 🛑\n",
    "\n",
    "Esto **no** es un error: es Git negándose a pisar tres horas de tu trabajo con lo que viene de fuera. Si no existiera esa negativa, el `pull` se llevaría tus cambios sin avisar.\n",
    "\n",
    "Hay dos salidas y las dos son de un capítulo anterior: hacer un commit aunque esté a medias, o mandarlo al cajón con `git stash`, que es 8.\n",
    "\n",
    "Lo que no hay que hacer es lo que hace mucha gente: borrar el archivo para que el pull \"pase\". Eso no resuelve el conflicto, lo tapa tirando tu trabajo."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprueba que se entendió"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comprueba que lo tienes\n",
    "\n",
    "Quieres ver qué subió el equipo sin que te cambie nada todavía. ¿Qué comando usas?\n",
    "\n",
    "a) `git fetch`\n",
    "\n",
    "b) `git pull`\n",
    "\n",
    "c) `git status`\n",
    "\n",
    "d) `git log`\n",
    "\n",
    "---\n",
    "\n",
    "**La correcta es la a.**\n",
    "\n",
    "*b)* Pull trae y además mezcla en tus archivos, que es justo lo que no querías todavía.\n",
    "\n",
    "*c)* Status mira lo que tienes en tu máquina; no pregunta nada al servidor.\n",
    "\n",
    "*d)* Log lee la historia que ya tienes bajada. Lo nuevo de allá no está ahí hasta que lo traigas.\n",
    "\n",
    "`fetch` mira, `pull` mezcla 👀"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Monta un proyecto con dos personas\n",
    "\n",
    "Un repositorio, un servidor y dos copias."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cd ..\n",
    "mkdir tienda\n",
    "cd tienda\n",
    "git init -q\n",
    "printf 'bodega,ciudad\\nBodega Inti,Cusco\\n' > bodegas.csv\n",
    "git add bodegas.csv\n",
    "git commit -q -m \"Catalogo inicial de bodegas\"\n",
    "cd ..\n",
    "git clone -q --bare tienda tienda-servidor.git\n",
    "cd tienda\n",
    "git remote add origin ../tienda-servidor.git\n",
    "git push -q -u origin main\n",
    "cd ..\n",
    "git clone -q tienda-servidor.git tienda-rosa\n",
    "cd tienda-rosa\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "a9874ae Catalogo inicial de bodegas\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dos copias del mismo proyecto, cada una en su carpeta."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Que la otra persona suba algo\n",
    "\n",
    "Desde la segunda copia, agrega un minimarket y súbelo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "printf 'Minimarket Sol,Trujillo\\n' >> bodegas.csv\n",
    "git add bodegas.csv\n",
    "git commit -q -m \"Entra el minimarket de Trujillo\"\n",
    "git push -q origin main\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "4cb519a Entra el minimarket de Trujillo\n",
    "a9874ae Catalogo inicial de bodegas\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dos commits allá. La primera copia todavía no lo sabe."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Mira sin mezclar\n",
    "\n",
    "Desde la primera copia, trae la información sin tocar tus\n",
    "archivos."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "cd ../tienda\n",
    "git fetch -q origin\n",
    "git status --short --branch\n",
    "cat bodegas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "## main...origin/main [behind 1]\n",
    "bodega,ciudad\n",
    "Bodega Inti,Cusco\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`behind 1` y tu archivo intacto. Eso es `fetch`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Averigua qué te vas a traer\n",
    "\n",
    "Los commits que están allá y aquí no."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log --oneline HEAD..origin/main\n",
    "git diff --stat HEAD origin/main"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "4cb519a Entra el minimarket de Trujillo\n",
    " bodegas.csv | 1 +\n",
    " 1 file changed, 1 insertion(+)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un commit, un archivo, una línea. Ya sabes a qué atenerte."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Ponte al día\n",
    "\n",
    "Ahora sí, mezcla."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git merge -q origin/main\n",
    "cat bodegas.csv\n",
    "git status --short --branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "bodega,ciudad\n",
    "Bodega Inti,Cusco\n",
    "Minimarket Sol,Trujillo\n",
    "## main...origin/main\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Al día. `fetch` más `merge` es `pull`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Haz la rutina de la mañana\n",
    "\n",
    "Bajar, y recién ahí crear tu rama del día."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git pull -q --no-rebase origin main\n",
    "git switch -q -c catalogo-de-horeca\n",
    "git status --short --branch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "## catalogo-de-horeca\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tu rama nace de la versión de hoy, no de la del lunes pasado 📅"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Provoca la negativa del pull\n",
    "\n",
    "Deja un cambio sin guardar y trata de bajar lo del\n",
    "equipo."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git switch -q main\n",
    "cd ../tienda-rosa\n",
    "git pull -q --no-rebase origin main\n",
    "sed -i 's/Bodega Inti,Cusco/Bodega Inti,Arequipa/' bodegas.csv\n",
    "git add bodegas.csv\n",
    "git commit -q -m \"La bodega Inti se mudo a Arequipa\"\n",
    "git push -q origin main\n",
    "cd ../tienda\n",
    "printf 'Mayorista Norte,Piura\\n' >> bodegas.csv\n",
    "git pull --no-rebase origin main"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "From ../tienda-servidor\n",
    " * branch            main       -> FETCH_HEAD\n",
    "   4cb519a..45f0337  main       -> origin/main\n",
    "error: Your local changes to the following files would be overwritten by merge:\n",
    "\tbodegas.csv\n",
    "Please commit your changes or stash them before you merge.\n",
    "Aborting\n",
    "Updating 4cb519a..45f0337\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Git te frena en vez de pisarte. Guarda o manda al cajón, y vuelve a\n",
    "intentarlo 🛑"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lo que te llevas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Fetch mira, pull mezcla. Baja antes de empezar y trabaja en tu\n",
    "rama.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 22 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/trabajar-sin-pisarse/\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
}
