{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Leer la historia sin abrir un archivo\n",
    "\n",
    "Buscar en el pasado del proyecto y saber quién escribió cada línea\n",
    "\n",
    "Cuaderno de práctica del capítulo 6 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-la-historia/\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: \"NWZmNzAxNyBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgVHJ1amlsbG8KNTcxODc3YiBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgQXJlcXVpcGEKNTRkYTZlMiBQcmltZXJhcyB2ZW50YXMgZGUgTGltYQ==\",\n",
    "    2: \"Y29tbWl0IDVmZjcwMTdhNDJmN2ZmOTUxZjNmOTUwMDdjYWNhNDc0YzNlOTUxODgKQXV0aG9yOiBNaXNzIFllcmEgPGhvbGFAbWlzc3llcmEuY29tPgpEYXRlOiAgIFRodSBKYW4gMTUgMDk6MDA6MDAgMjAyNiAtMDUwMAoKICAgIFNlIGFncmVnYW4gbGFzIHZlbnRhcyBkZSBUcnVqaWxsbwoKZGlmZiAtLWdpdCBhL3ZlbnRhcy5jc3YgYi92ZW50YXMuY3N2CmluZGV4IDBjODA4NzcuLjI5NjExMjggMTAwNjQ0Ci0tLSBhL3ZlbnRhcy5jc3YKKysrIGIvdmVudGFzLmNzdgpAQCAtMSwzICsxLDQgQEAKIGNpdWRhZCxtb250bwogTGltYSwxMjAwCiBBcmVxdWlwYSw4OTAKK1RydWppbGxvLDE0NTA=\",\n",
    "    3: \"KiA1ZmY3MDE3IFNlIGFncmVnYW4gbGFzIHZlbnRhcyBkZSBUcnVqaWxsbwoqIGU0ZWI4NmIgU2UgYWdyZWdhIGVsIGNhdGFsb2dvIGRlIGNsaWVudGVzCiogNTcxODc3YiBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgQXJlcXVpcGEKKiA1NGRhNmUyIFByaW1lcmFzIHZlbnRhcyBkZSBMaW1h\",\n",
    "    4: \"NWZmNzAxNyBTZSBhZ3JlZ2FuIGxhcyB2ZW50YXMgZGUgVHJ1amlsbG8KIHZlbnRhcy5jc3YgfCAxICsKIDEgZmlsZSBjaGFuZ2VkLCAxIGluc2VydGlvbigrKQ==\",\n",
    "    5: \"ZTRlYjg2YiBTZSBhZ3JlZ2EgZWwgY2F0YWxvZ28gZGUgY2xpZW50ZXM=\",\n",
    "    6: \"YXV0aG9yIE1pc3MgWWVyYQ==\",\n",
    "    7: \"ZmF0YWw6IHBhdGggJ2NsaWVudGVzLmNzdicgZXhpc3RzIG9uIGRpc2ssIGJ1dCBub3QgaW4gJ0hFQUR+Myc=\",\n",
    "}, lenguaje=\"bash\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Preparo una historia para husmear"
   ]
  },
  {
   "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",
    "git add ventas.csv\n",
    "git commit -q -m \"Primeras ventas de Lima\"\n",
    "printf 'Arequipa,890\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Arequipa\"\n",
    "printf 'bodega,ciudad\\nBodega Sol,Lima\\n' > clientes.csv\n",
    "git add clientes.csv\n",
    "git commit -q -m \"Se agrega el catalogo de clientes\"\n",
    "printf 'Trujillo,1450\\n' >> ventas.csv\n",
    "git add ventas.csv\n",
    "git commit -q -m \"Se agregan las ventas de Trujillo\"\n",
    "git log --oneline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Filtrar, que es de lo que se trata"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un proyecto real tiene miles de commits, así que el log casi nunca se lee\n",
    "entero. Se filtra.\n",
    "\n",
    "Por lo que dice el mensaje:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log --oneline --grep=\"ventas\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Por el archivo que tocaron:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log --oneline -- clientes.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ese guion doble separa los commits de los archivos. Sin él, Git no sabe si\n",
    "`clientes.csv` es una rama o un archivo 📁\n",
    "\n",
    "Y los últimos, que es lo que más se usa:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git log --oneline -2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ver un momento por dentro"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`git show` abre un commit y te enseña qué cambió en él:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git show --stat --oneline HEAD~1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "El `--stat` resume; sin él te muestra las líneas una por una. Y\n",
    "`HEAD~1` es \"uno antes del actual\", que ya usamos en el capítulo\n",
    "1."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Quién escribió esta línea"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Este es el comando que más me sorprendió cuando lo descubrí:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%consola\n",
    "git blame ventas.csv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cada línea del archivo, con el commit del que salió y quién la escribió.\n",
    "Cuando entras a un proyecto que no conoces y encuentras algo raro, esto te lleva\n",
    "directo al momento en que se puso ahí, y al mensaje que lo explica 🔦"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## El error de pedir un commit que no existe"
   ]
  },
  {
   "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 show inventado123"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Y la queja que tiene que salir es esta:\n",
    "\n",
    "```\n",
    "fatal: ambiguous argument 'inventado123': unknown revision or path not in the working tree.\n",
    "Use '--' to separate paths from revisions, like this:\n",
    "'git <command> [<revision>...] -- [<file>...]'\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Ambiguous* porque Git no sabe si le pediste un commit o un archivo, y\n",
    "no encontró ninguno de los dos. De ahí sale el consejo del guion doble que te\n",
    "da en el propio mensaje."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### La trampa\n",
    "\n",
    "Te toca revisar por qué el reporte de ventas de Lima salió mal el mes pasado. Miras el log del proyecto y ves solo tres commits en todo el mes, así que concluyes que casi nadie tocó nada.\n",
    "\n",
    "```\n",
    "$ git log --oneline\n",
    "\n",
    "4f2a91c Se corrige el reporte\n",
    "8c1b03e Ajustes\n",
    "2d9e77a Actualizacion mensual\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",
    "Quieres saber en qué commit se rompió una línea concreta de un archivo. ¿Con qué empiezas?\n",
    "\n",
    "a) `git log` y vas abriendo commits uno por uno\n",
    "\n",
    "b) `git blame` sobre ese archivo\n",
    "\n",
    "c) `git status`\n",
    "\n",
    "d) Abrir el archivo y buscar a ojo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Los commits de un solo archivo\n",
    "\n",
    "Pide la historia de `ventas.csv` nada más."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 1\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Qué entró exactamente en el último commit\n",
    "\n",
    "Muestra las líneas que cambiaron, no el resumen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 2\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. La historia con su dibujo\n",
    "\n",
    "Pide el log con el gráfico de ramas, aunque todavía haya\n",
    "una sola."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 3\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Cuántas líneas cambió cada commit\n",
    "\n",
    "Pide la historia con el resumen de líneas de cada uno."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 4\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Busca por lo que NO dice\n",
    "\n",
    "Encuentra los commits cuyo mensaje no mencione ventas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 5\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Quién escribió el catálogo de clientes\n",
    "\n",
    "Pide el blame del CSV de clientes con el formato corto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%revisa 6\n",
    "# tu turno"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. Pide un archivo que no está en ese commit\n",
    "\n",
    "Intenta ver `clientes.csv` en el primer commit,\n",
    "cuando todavía no existía."
   ]
  },
  {
   "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": [
    "**La historia se filtra, no se lee entera. Y blame no es para culpar,\n",
    "es para encontrar el porqué.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "Ese era el capítulo 6 de **Git desde cero**. El texto completo, con las salidas de cada bloque, está en https://missyera.com/guias/git-desde-cero/leer-la-historia/\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
}
