Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 70: Git, GitHub y control de versiones

100 Días de Código en Python — Día 70: Git, GitHub y control de versiones

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 70 (nivel avanzado).

Este tutorial adapta pedagógicamente el Día 70. Las secciones 📝 Contenido original del curso provienen de las lecciones 501 a 510. Los retos 🟢🟡🟠🔴, las secciones sobre autenticación en GitHub, secretos filtrados y privacidad, el proyecto extra y el proyecto integrador final del bloque avanzado (Días 59 a 70) son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.

Nota sobre las verificaciones: el 27 de septiembre de 2026, con Git 2.55.0 para Windows, se ejecutó el flujo del curso usando un repositorio remoto local (sin GitHub): init, add, commit, log, diff, remote add, push -u, .gitignore y rm --cached. Se comprobó que, sin configuración previa, git init todavía crea la rama master (Git anuncia que cambiará a main en Git 3.0), y que en ese caso git push -u origin main, como indica el curso, falla con error: src refspec main does not match any. También se comprobó que un archivo que ya se guardó en un commit sigue en el historial aunque después se agregue a .gitignore. No se usó una cuenta de GitHub.

🏫 Para el aula: GitHub exige tener al menos 13 años. Para cuentas de estudiantes, usa un nombre de usuario que no revele tu nombre completo y el correo privado que ofrece GitHub (sección 3). Existe GitHub Education, con beneficios gratuitos para estudiantes y docentes.


Tabla de contenidos

  1. Antes de empezar: la terminal y Git Bash
  2. ¿Qué es el control de versiones?
  3. Git en tu computador: las tres áreas
  4. GitHub y los repositorios remotos
  5. .gitignore: lo que nunca debe subirse
  6. Clonar repositorios
  7. Ramas y fusiones
  8. Forks y pull requests: colaborar
  9. 🚀 Proyecto del día: la historia colaborativa
  10. 🌟 Proyecto extra: el portafolio del bloque en GitHub
  11. 🏆 Proyecto integrador final del bloque avanzado (Días 59 a 70)
  12. 🧩 Comprueba lo aprendido
  13. 🤖 Programar con apoyo de IA
  14. 🛠️ Correcciones técnicas al material original
  15. 📋 Matriz de trazabilidad
  16. 📦 Evidencias de aprendizaje del Día 70

0. Antes de empezar: la terminal y Git Bash

(Fuentes: 501-the-terminal-use-either-vs-code-or-pycharm.md y 502 - Install Git Bash on Windows.md)

📝 Contenido original del curso

Hoy se trabaja en la terminal (Día 54). En los videos se usa la de VS Code, pero "una terminal es una terminal": la de PyCharm sirve igual. Windows no trae Bash ni Git, así que hay que instalar Git Bash:

  1. Descargar Git para Windows (Git SCM) y abrir el instalador.
  2. Aceptar la licencia y la ubicación; en los componentes, verificar que Git Bash esté marcado; dejar el resto de opciones por defecto ("Siguiente, Siguiente, Siguiente").
  3. Comprobarlo en VS Code: Terminal → Nueva terminal, y en el menú junto al "+", elegir Git Bash (aparece un signo $).
  4. Para que siempre abra Git Bash: Ver → Paleta de comandos → "Terminal: Select Default Profile" → Git Bash.

En Mac, Bash (o zsh) y, normalmente, Git ya vienen instalados.

Prerequisitos: línea de comandos (Día 54), .env y secretos (Días 35 y 61), el proyecto del blog y la Plataforma del Club (Días 59 a 69).

📖 Dos configuraciones del primer día (adaptación)

Antes del primer commit, Git necesita saber quién eres:

Terminal
git config --global user.name "Tu nombre o seudónimo"
git config --global user.email "tu-correo@example.com"     # en GitHub, mejor el correo privado (sección 3)
git config --global init.defaultBranch main                 # para que las ramas nuevas se llamen main
git config --global core.editor "code --wait"               # usar VS Code para los mensajes, en lugar de Vim

🛠️ Nota técnica (verificado): sin la tercera línea, Git 2.55 todavía llama master a la rama inicial (y avisa que cambiará a main en Git 3.0). El curso usa main en todos sus comandos; configurar init.defaultBranch evita el error de la sección 3. El instalador de Git para Windows también pregunta por este nombre.


1. ¿Qué es el control de versiones?

(Fuente: 503 - Introduction to Version Control and Git.md)

📝 Contenido original del curso

Escribes un archivo de código y lo pones bajo control de versiones con Git: punto de guardado 1. Escribes más: punto de guardado 2. Luego arruinas el archivo de forma irreparable ("preferiría quemarlo antes que arreglarlo"), algo que pasa porque el código está interconectado. Con Git puedes:

  • comparar tu archivo actual con cualquier punto de guardado anterior;
  • volver a cualquier versión, no solo a la inmediatamente anterior, hacia atrás o hacia adelante.

📖 Por qué te importa (adaptación)

¿Alguna vez has tenido trabajo_final.py, trabajo_final_v2.py, trabajo_final_ahora_si.py? Git reemplaza esa colección de copias por una carpeta con todo su historial: qué cambió, cuándo, quién y por qué (el mensaje de cada commit).


2. Git en tu computador: las tres áreas

(Fuente: 504 - Version Control using Git and the Command Line.md)

🎯 Objetivo de aprendizaje

Crear un repositorio, mover cambios entre las áreas de Git, crear commits con buenos mensajes y recuperar un archivo arruinado.

📝 Contenido original del curso

En el escritorio, la profesora crea la carpeta Story, entra y crea chapter1.txt con touch; escribe algo y guarda.

Comando Qué hace
git init Crea un repositorio Git vacío en la carpeta (una carpeta oculta .git, visible con ls -a)
git status Muestra el estado: archivos sin seguimiento en rojo, preparados en verde
git add chapter1.txt Pasa el archivo al área de preparación (staging area)
git add . Pasa todo lo de la carpeta actual
git commit -m "Complete chapter 1" Crea el punto de guardado con un mensaje
git log Lista los commits: autor, fecha, hash único y mensaje; HEAD indica dónde estás
git diff chapter3.txt Muestra las diferencias con el último commit (rojo: borrado; verde: agregado)
git checkout chapter3.txt Devuelve el archivo a como estaba en el último commit

Las tres áreas:

Texto
Directorio de trabajo  ──git add──▶  Área de preparación  ──git commit──▶  Repositorio local
      (Story)                          (staging)                              (.git)
         ▲                                                                       │
         └──────────────────── git checkout / git restore ◀──────────────────────┘

¿Por qué existe el área de preparación y no se va directo al repositorio? Porque a veces no quieres guardar todos los archivos: ahí eliges qué entra en el commit.

Mensajes de commit: lo más explícitos posible sobre qué cambió desde el punto anterior y, por convención, en tiempo presente ("Complete chapter 1", no "Completed…"): "como si estuvieras enviando tus cambios ahora".

La historia del capítulo 3: la profesora "se queda dormida sobre el teclado" y guarda un capítulo lleno de basura. Con git diff ve qué cambió y con git checkout chapter3.txt recupera la versión del último commit.

📖 Explicación conceptual (verificada con Git 2.55)

🛠️ Nota técnica: git checkout sirve para demasiadas cosas (cambiar de rama, restaurar archivos…) y por eso Git agregó comandos más claros: git restore archivo para descartar cambios en un archivo (verificado: devuelve el contenido del último commit) y git switch rama para cambiar de rama. Los dos estilos funcionan; los nuevos son más difíciles de confundir.

⚠️ git restore (o git checkout archivo) borra los cambios sin guardar de ese archivo y no hay papelera. Mira primero con git diff.

En Windows verás avisos como LF will be replaced by CRLF: Windows y Mac/Linux marcan el final de línea distinto y Git lo convierte. Es normal y no es un error.

⚠️ Errores frecuentes

Error Causa Solución
fatal: not a git repository Estás en una carpeta sin git init (o fuera de ella) pwd y cd a la carpeta correcta
Author identity unknown / Please tell me who you are Falta user.name y user.email Sección 0
nothing to commit Olvidaste git add o no hay cambios git status
Hiciste git init en tu carpeta de usuario Git empieza a rastrear todo tu computador Borra esa carpeta .git (¡solo esa!) con cuidado
El mensaje queda en un editor raro (Vim) Hiciste git commit sin -m En Vim: escribe el mensaje, Esc, :wq y Enter; o configura VS Code como editor

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1 — Aplicación: crea un repositorio con un poema de tres estrofas, un commit por estrofa, y muestra el historial con git log --oneline.
  • 🟡 Reto 2 — Ampliación: arruina una estrofa, compárala con git diff y recupérala con git restore.
  • 🟠 Reto 3 — Desafío: modifica dos archivos y haz dos commits separados, uno por archivo, usando el área de preparación. ¿Por qué eso hace el historial más útil?
  • 🔴 Reto 4 — Pensamiento computacional: lee git log de un proyecto tuyo y escribe, solo con los mensajes, la "historia" del proyecto. ¿Se entiende? Reescribe (en papel) tres mensajes para que sean más claros.

3. GitHub y los repositorios remotos

(Fuente: 505 - Github and Remote Repositories.md)

📝 Contenido original del curso

Un repositorio remoto está alojado en el servidor de otra persona, como GitHub. Crear una cuenta es gratis (solo hay que confirmar el correo).

  1. En GitHub, "+" → New repository, nombre "Story" y una descripción ("Mi obra maestra").
  2. Público o privado: por defecto son públicos; cualquiera ve todos los archivos. Salvo que sea algo secreto, no suele haber problema, y a cambio puedes ver el código de otros (por ejemplo, implementaciones completas de Flappy Bird): "la belleza del código abierto".
  3. Sin README por ahora → Create repository.
  4. Con las instrucciones de línea de comandos, subir el repositorio local existente:
Terminal
   git remote add origin https://github.com/usuario/Story.git
   git push -u origin main
  • origin es el nombre del remoto; podría llamarse "bacon", pero por convención se usa origin para que otros programadores entiendan tu proyecto.
  • -u vincula la rama local con la remota (después basta con git push).
  • main es la rama principal, la línea de tiempo por defecto de los commits.
  1. Al recargar GitHub aparecen los archivos y los commits; en Insights → Network se ve la rama y sus puntos de guardado. Al hacer clic en un commit se ven sus cambios.

Hay quien escribe historias enteras en GitHub, por lo bueno que es para seguir versiones. Resumen: directorio de trabajo → preparación → repositorio local → (git push) → repositorio remoto.

📖 Lo que el video no muestra (adaptación)

🛠️ Nota técnica (verificado): si tu rama local se llama master (el valor de fábrica de Git, sección 0), git push -u origin main falla:

Texto
error: src refspec main does not match any
error: failed to push some refs

Solución: renombra la rama (git branch -M main, el mismo comando que muestra GitHub en sus instrucciones) o configura init.defaultBranch main antes de crear repositorios.

🛠️ Nota técnica: desde 2021, GitHub no acepta tu contraseña en la terminal. Git para Windows incluye Git Credential Manager, que abre el navegador para que inicies sesión de forma segura la primera vez que haces push. En otros sistemas se usa un token de acceso personal o una clave SSH. Nunca pegues un token en el código ni en un chat.

Privacidad: cada commit guarda el nombre y el correo que configuraste, y en un repositorio público cualquiera los ve. En GitHub, en Settings → Emails, activa "Keep my email addresses private" y usa como user.email la dirección ...@users.noreply.github.com que te asigna.

⚠️ Errores frecuentes

Error Causa Solución
src refspec main does not match any La rama local se llama master (o no tienes commits) git branch -M main
remote origin already exists Ya agregaste el remoto git remote -v para verlo; git remote set-url origin URL para cambiarlo
Authentication failed Usaste la contraseña de la cuenta Inicia sesión con el navegador (Credential Manager) o usa un token
rejected ... fetch first El remoto tiene commits que tú no (por ejemplo, creaste el README en GitHub) git pull primero, luego git push

4. .gitignore: lo que nunca debe subirse

(Fuente: 506 - Gitignore.md)

🎯 Objetivo de aprendizaje

Excluir del repositorio los secretos, los entornos virtuales y los archivos personales, y saber qué hacer si un secreto ya se subió.

📝 Contenido original del curso

En una carpeta Project con file1.txt, file2.txt, file3.txt y un archivo de secretos: hay archivos que no quieres en un repositorio, y menos en uno público. "Hay historias de terror": personas que subieron sus claves de Amazon AWS a GitHub y en segundos alguien usó su cuenta. Tampoco conviene subir archivos de configuración personal, como .DS_Store de Mac (cómo tienes ordenados los íconos de una carpeta).

Cómo se usa:

  1. Crear el archivo .gitignore (con el punto; el nombre exacto importa).
  2. Si ya agregaste todo al área de preparación, deshacerlo con git rm --cached -r ..
  3. En .gitignore, un nombre de archivo por línea (.DS_Store, secrets.txt); # para comentarios; comodines como *.txt.
  4. git add . y git status: los archivos ignorados ya no aparecen.

Para proyectos Python: el repositorio github/gitignore tiene plantillas listas; la de Python ya excluye entornos virtuales y otros archivos que no sirven a tus colaboradores. Copia su contenido a tu .gitignore y agrega lo propio (por ejemplo, .DS_Store). Y la respuesta a "¿dónde pongo mis claves?": en archivos que estén en .gitignore.

📖 Un .gitignore para tus proyectos Flask (adaptación)

gitignore
# Entornos virtuales
venv/
.venv/

# Secretos (Días 35, 61, 64, 68)
.env

# Base de datos local de Flask-SQLAlchemy (Día 63)
instance/
*.db

# Python
__pycache__/
*.pyc

# Editores y sistema
.idea/
.vscode/
.DS_Store
Thumbs.db

Y sube, en cambio, un .env.ejemplo con los nombres de las variables y valores falsos, para que quien clone el proyecto sepa qué configurar.

📖 Si un secreto ya se subió (adaptación, verificado)

.gitignore solo afecta a archivos que todavía no están rastreados. Verificado: después de hacer commit de un .env y luego agregarlo a .gitignore y ejecutar git rm --cached .env, el archivo deja de rastrearse… pero sigue en el historial: git log --all -- .env todavía muestra el commit que lo contenía, y cualquiera puede recuperarlo.

Por eso, si subiste una clave:

  1. Revócala o cámbiala de inmediato en el servicio (TMDB, Gmail, la clave secreta de Flask…). Es el único paso que de verdad te protege.
  2. Deja de rastrear el archivo (git rm --cached .env) y agrégalo a .gitignore.
  3. Si el repositorio es público, considera borrar el secreto del historial con herramientas especializadas; pero asume que ya fue visto.

GitHub, además, analiza los repositorios públicos en busca de claves conocidas (secret scanning) y puede bloquear el push si detecta una.

⚠️ Errores frecuentes

Error Causa Solución
El archivo sigue apareciendo aunque está en .gitignore Ya estaba rastreado git rm --cached archivo y commit
.gitignore no hace nada Se llama gitignore.txt (Windows ocultó la extensión) Créalo desde la terminal o el editor; revisa con ls -a
Subiste venv/ (miles de archivos) Faltó la plantilla de Python Agrégalo a .gitignore y git rm -r --cached venv
Nadie puede ejecutar tu proyecto Ignoraste también requirements.txt Ese sí se sube

5. Clonar repositorios

(Fuente: 507 - Cloning.md)

📝 Contenido original del curso

Clonar (git clone URL) trae a tu computador todo un repositorio remoto, con todas sus versiones y commits. Así puedes "subirte a hombros de gigantes": adaptar un programa, ampliarlo o corregir un error. Muchas empresas usan aplicaciones autoalojadas (alternativas gratuitas a Jira, Trello o Mailchimp) que clonan y ejecutan en sus servidores.

Ejemplos del video:

  • QuakeJS: el videojuego Quake original en el navegador, hecho en JavaScript. Se clona, se instalan sus paquetes con npm install, se configura su servidor de contenidos y se ejecuta con Node; queda en el puerto 8080.
  • Wordle en Python: un clon hecho con Tkinter (lo conoces). Se clona, se crea el entorno virtual, se instalan los requisitos y se juega sin el límite de una palabra al día. "Estudiar el código de otros y modificarlo te hace mejor desarrollador".

Para empezar a contribuir al código abierto, el repositorio awesome-for-beginners reúne proyectos acogedores con quienes contribuyen por primera vez (por ejemplo, pandas o Matplotlib).

📖 Clonar con criterio (adaptación)

  • QuakeJS necesita Node.js y npm, que no has instalado en este curso; el ejemplo de Wordle en Python es más fácil de reproducir.
  • Antes de ejecutar código ajeno, léelo (al menos el README y el archivo principal) y revisa que el proyecto sea conocido o confiable. Clonar y ejecutar cualquier cosa es como abrir cualquier adjunto de un correo.
  • Respeta la licencia del repositorio (archivo LICENSE, Día 56): dice qué puedes hacer con el código.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: clona un repositorio pequeño en Python (por ejemplo, un juego con Tkinter o Turtle), crea su entorno virtual con requirements.txt y ejecútalo.
  • 🟡 Reto 2: haz un cambio visible (colores, textos en español) y un commit en tu copia local.
  • 🟠 Reto 3: en git log, encuentra el commit en el que se agregó una función que te interese y explica con git show qué cambió.

6. Ramas y fusiones

(Fuentes: 508 - Branching and Merging.md y 509-optional-git-challenge.md)

🎯 Objetivo de aprendizaje

Crear ramas para experimentar sin afectar la rama principal, y fusionarlas.

📝 Contenido original del curso

Después de dos commits, quieres probar una idea nueva sin tocar el proyecto principal: creas una rama y haces commits allí, mientras sigues trabajando en main. Si el experimento sale bien, lo fusionas (merge) con main, revisando si hay conflictos. En proyectos grandes se trabaja en varias ramas a la vez (funciones nuevas, correcciones) y solo se lleva a main lo que funciona, porque main es lo que se publica.

En el repositorio Story:

Terminal
git branch alien-plot          # crea la rama
git branch                     # lista las ramas; * marca la actual
git checkout alien-plot        # cambia a la rama
# ...cambios en los capítulos 1 y 2...
git add .
git commit -m "Modify chapter 1 and 2 to have alien theme"
git checkout main              # vuelve a main: los capítulos NO tienen los cambios alienígenas
# ...crear chapter4.txt...
git add .
git commit -m "Add chapter 4"
git merge alien-plot           # desde main, trae los cambios de la rama
git push -u origin main

Al fusionar se abre Vim para el mensaje de la fusión; la profesora sale con :q! y el merge queda hecho. En GitHub, Insights → Network dibuja el proceso: la rama que se separa y vuelve a unirse. Al cambiar de rama, los archivos de la carpeta cambian para reflejar esa rama.

La profesora recomienda separar siempre git add y git commit al empezar, "para saber exactamente lo que está pasando".

Reto opcional (lección 509): learngitbranching.js.org, con ejercicios sobre cherry-pick, rebase y más.

📖 Explicación conceptual (adaptación)

🛠️ Nota técnica: en Vim, :q! significa "salir sin guardar", no "guardar y salir" (eso es :wq). Funciona en este caso porque Git ya escribió un mensaje por defecto ("Merge branch 'alien-plot'") en el archivo. Si configuras VS Code como editor (sección 0), aparece el mensaje en VS Code: cierras la pestaña y listo. Para evitar el editor: git merge alien-plot -m "Merge alien plot".

Conflictos. Si en main y en la rama se cambió la misma línea, Git no sabe cuál quedarse y marca el archivo:

Texto
<<<<<<< HEAD
Había una vez un pueblo tranquilo.
=======
Había una vez una nave extraterrestre.
>>>>>>> alien-plot

Tú decides: editas el archivo, dejas la versión correcta (o una mezcla), borras las marcas y haces git add y git commit. No es un error: es Git pidiéndote una decisión.

Comandos modernos: git switch -c alien-plot (crear y cambiar) y git switch main.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: en tu poema, crea una rama version-triste, cambia el final y fusiónala.
  • 🟡 Reto 2: provoca a propósito un conflicto (misma línea en ambas ramas) y resuélvelo.
  • 🟠 Reto 3: en el blog del Día 69, crea una rama modo-oscuro, implementa el modo oscuro de Bootstrap (Día 58) y fusiónala solo cuando funcione.
  • 🔴 Reto 4: completa los primeros niveles de learngitbranching.js.org y explica con tus palabras qué hace git rebase y en qué se diferencia de git merge.

7. Forks y pull requests: colaborar

(Fuente: 510 - Forking and Pull Requests.md)

📝 Contenido original del curso

Las cuatro áreas: directorio de trabajo, preparación, repositorio local y repositorio remoto. Ahora, la colaboración entre dos cuentas:

  • Angela es dueña del repositorio remoto. Su "gemela malvada", Bangela, quiere contribuir.
  • Clonar copia un repositorio a tu computador. Hacer fork copia un repositorio de GitHub a tu cuenta de GitHub; esa copia es tuya y puedes modificarla.
  • Solo las personas de confianza (un equipo) tienen permiso de escritura en el repositorio original. El resto contribuye así: fork → cambios → commit → push a su copia → Pull request.
  • Se llama pull request (y no push request) porque el dueño decide si trae (pull) los cambios: los revisa, comenta y, si le gustan, los fusiona.

La demostración: desde la cuenta "gilfoyleismyothername", la profesora hace fork de angelabauer/Story, cambia el capítulo 4 en la copia ("Add more space-themes in chapter 4") y crea un pull request explicando por qué merece fusionarse ("siempre ayuda ser elogioso"). En el repositorio original no cambia nada hasta que la cuenta de Angela revisa el pull request, comenta "¡Gran trabajo, Gilfoyle!" y pulsa Merge pull request. La red de GitHub muestra la rama del fork uniéndose a la principal.

Ejemplo real: el proyecto Alamofire tenía miles de forks y cientos de pull requests cerrados: desde actualizar un README hasta correcciones documentadas con objetivos, detalles y pruebas, que el dueño revisa y a veces pide ajustar. GitHub es "casi una red social para programadores": contribuir con correcciones o funciones a las bibliotecas que usas es una forma de devolver al código abierto.

📖 Un buen pull request (adaptación)

Parte Ejemplo
Título claro "Corrige el error 500 de @admin_only con visitantes anónimos"
Qué y por qué "Un visitante sin sesión provocaba AttributeError. Ahora se comprueba is_authenticated."
Cómo se probó "Probado con anónimo (403), lector (403) y administrador (200)."
Alcance pequeño Un cambio por pull request: más fácil de revisar
Tono Respetuoso; agradece el trabajo existente

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: en parejas, cada uno hace fork del repositorio del otro, corrige un error de ortografía y abre un pull request.
  • 🟡 Reto 2: revisa el pull request que te hicieron: deja un comentario en una línea concreta, pide un cambio y apruébalo cuando lo corrijan.
  • 🟠 Reto 3: busca en awesome-for-beginners un proyecto en Python y lee su guía de contribución (CONTRIBUTING.md). Resume en 5 puntos qué piden.

8. 🚀 Proyecto del día: la historia colaborativa

(Integra las lecciones 504 a 510, basado en el ejemplo Story del curso.)

Problema

Un grupo quiere escribir una historia entre varias personas sin perder versiones ni pisarse el trabajo.

Contexto

Es el mismo flujo con el que trabajan los equipos de software: cada persona en su rama o su fork, revisión antes de integrar y un historial que explica cada cambio.

Objetivo

Un repositorio historia-del-curso en GitHub con una historia de al menos 4 capítulos, construida con commits claros, al menos una rama fusionada y al menos dos pull requests de compañeros.

Requisitos funcionales

  1. git init, .gitignore y el capítulo 1 con un commit en tiempo presente.
  2. Capítulos 2 y 3 en un commit aparte; git log limpio.
  3. Un capítulo arruinado a propósito y recuperado con git diff y git restore.
  4. Subida a GitHub con origin y main.
  5. Una rama con un giro argumental, fusionada con main (con al menos un conflicto resuelto).
  6. Dos compañeros hacen fork y pull request (un capítulo nuevo cada uno); el dueño revisa, comenta y fusiona.

Restricciones técnicas

  • Mensajes en tiempo presente y descriptivos.
  • Nada de datos personales en los textos ni en la configuración de Git (correo privado de GitHub).

Planificación

  1. Comprender el flujo. 2. Entradas: los capítulos. 3. Procesos: guardar versiones, ramificar, fusionar, colaborar. 4. Salidas: el repositorio y su historial. 5. Dividir: local → remoto → ramas → colaboración. 6. Diseñar la trama y quién escribe qué. 7. Implementar. 8. Revisar el gráfico de Network. 9. Corregir. 10. Mejorar el README.

Construcción paso a paso

  • Versión 1: repositorio local con 3 capítulos.
  • Versión 2: en GitHub.
  • Versión 3: rama con giro argumental y fusión.
  • Versión final: pull requests de compañeros y un README.md con el resumen y los autores (con su permiso).

Pruebas

Caso Evidencia
Historial git log --oneline --graph --all muestra la rama y la fusión
Recuperación Captura de git diff antes de git restore
Conflicto Captura de las marcas <<<<<<< y del archivo resuelto
Colaboración Dos pull requests cerrados con comentarios
Privacidad Los commits muestran el correo noreply de GitHub

🧪 Prueba y depuración

Terminal
cd Documentos
git init
git add .
git commit -m "cambios"
git remote add origin https://github.com/usuario/historia.git
git push -u origin main

Encuentra cuatro problemas: git init en Documentos rastrearía toda esa carpeta (debe hacerse dentro de la carpeta del proyecto); falta .gitignore; el mensaje "cambios" no dice nada; y si la rama local se llama master, el push a main falla.

⭐ Extensión del proyecto

  • Etiquetar la versión final con git tag v1.0 y subir la etiqueta (git push --tags).
  • Publicar la historia como página web con GitHub Pages (en un archivo index.html generado con Jinja, Día 57).

9. 🌟 Proyecto extra: el portafolio del bloque en GitHub

(Proyecto creado para esta adaptación; no existe en el curso original.)

Situación

Terminaste el bloque web del curso (Días 54 a 69). Tus proyectos están en carpetas sueltas y nadie puede verlos. Un portafolio en GitHub es la carta de presentación de un programador.

Requisitos

  1. Sube tres proyectos del bloque (por ejemplo, el blog del Día 69, la API del Día 66 y "Mis 10 películas" del Día 64), cada uno en su repositorio, con:
    • .gitignore de Python con .env e instance/;
    • .env.ejemplo y requirements.txt;
    • README.md con descripción, capturas, instrucciones para ejecutarlo y qué aprendiste.
  2. Revisa el historial de cada repositorio antes de hacerlo público: ningún secreto, ninguna base de datos con usuarios reales.
  3. Un repositorio especial con tu nombre de usuario (el "README de perfil" de GitHub) que presente los tres proyectos.
  4. Un compañero clona uno de tus proyectos y lo ejecuta solo con tu README; anota dónde tuvo problemas y tú corriges el README.

Decisiones que debes tomar (y justificar)

  • ¿Qué proyectos te representan mejor? ¿Por qué?
  • ¿Público o privado? ¿Qué información personal dejas ver?

Casos de prueba

  • git log --all -- .env en cada repositorio no devuelve nada.
  • El compañero ejecuta el proyecto en menos de 10 minutos siguiendo el README.

10. 🏆 Proyecto integrador final del bloque avanzado (Días 59 a 70)

(Proyecto creado para esta adaptación. Se construyó por etapas desde el Día 59; aquí está su descripción completa y la etapa final.)

Situación problema

El club (de robótica, de lectura, ambiental, deportivo o de cualquier tipo) de tu colegio se organiza por mensajes sueltos, hojas de cálculo compartidas y carteleras de papel. La información se pierde, nadie sabe quién se inscribió en qué actividad y las noticias no llegan a tiempo.

Contexto

En este bloque aprendiste a construir aplicaciones web completas: formularios, bases de datos, APIs, usuarios con contraseñas seguras, diseño y control de versiones. Es exactamente lo que necesita una organización pequeña… siempre que se haga de forma segura, accesible y mantenible.

Pregunta orientadora

¿Cómo puede una aplicación web construida por estudiantes ayudar a un club escolar a comunicarse y organizarse, protegiendo los datos de sus miembros?

Objetivo

Construir la Plataforma del Club: una aplicación Flask con noticias, actividades e inscripciones, usuarios con roles, una API para otras aplicaciones, un diseño coherente y todo su desarrollo registrado en Git y GitHub.

Requerimientos

Funcionales

  1. Estructura y diseño (Días 59 y 65): plantilla Bootstrap con herencia (base.html), guía de estilo ESTILO.md con paleta y fuentes, contraste ≥ 4.5:1 medido con Python.
  2. Formularios (Días 60 a 62): contacto con correo al servidor local (EmailMessage); inscripciones con Flask-WTF y validadores; POST/Redirect/GET.
  3. Base de datos (Días 63 y 64): modelos Usuario, Noticia, Actividad, Comentario e inscripciones (muchos-a-muchos); CRUD completo.
  4. Contenido (Día 67): noticias con editor enriquecido y HTML limpiado con nh3; una plantilla para crear y editar; borrado con POST.
  5. Usuarios (Días 68 y 69): registro, inicio y cierre de sesión con Flask-Login; contraseñas con Werkzeug; roles (miembro, coordinador) con un decorador que responda 403 también a anónimos; comentarios solo para usuarios autenticados.
  6. API (Día 66): GET /api/actividades y GET /api/actividades/<id> públicos; POST, PATCH y DELETE con clave en la cabecera X-API-Key; códigos de estado correctos; API.md.
  7. Control de versiones (Día 70): repositorio en GitHub con historial claro, ramas por funcionalidad y al menos un pull request revisado por un compañero.

No funcionales

  • Seguridad: SECRET_KEY, claves de API y datos del correo en .env; ningún secreto en el historial de Git; debug desactivado en la versión de entrega.
  • Privacidad: solo datos ficticios o autorizados; ningún dato sensible de menores.
  • Accesibilidad: un h1 por página, alt en las imágenes, contraste verificado, formularios con etiquetas.
  • Mantenibilidad: README.md completo, requirements.txt, .env.ejemplo, código organizado (por ejemplo, forms.py, models.py).

Restricciones

  • Se ejecuta en la red local del colegio (127.0.0.1 o la IP que autorice el docente).
  • Correos solo al servidor local (aiosmtpd).
  • Nada de borrar con GET; nada de |safe sin limpiar.

Etapas de desarrollo

Etapa Día Producto
1. Estructura 59 Plantilla Bootstrap, include, rutas básicas, noticias desde JSON
2. Formularios 60 Contacto con correo, inscripción en CSV, POST/Redirect/GET
3. Formularios avanzados 61 Entorno virtual, herencia de plantillas, Flask-WTF, render_form
4. Datos en CSV 62 Actividades en CSV con tabla de Bootstrap
5. Base de datos 63 Migración del CSV a SQLAlchemy con migrar.py
6. CRUD 64 CRUD de actividades, validadores, (opcional) API del clima
7. Diseño 65 ESTILO.md, contraste medido, prueba de UX
8. API 66 Rutas /api/..., clave en cabecera, API.md, pruebas automáticas
9. Contenido 67 Noticias con editor y limpieza con nh3
10. Usuarios 68 Registro, inicio de sesión, rutas protegidas, flash
11. Roles y relaciones 69 Roles, decorador de coordinador, relaciones, comentarios
12. Versiones y publicación del código 70 Repositorio en GitHub, ramas, pull request, README final

Etapa 12 (hoy)

  1. Si aún no lo hiciste, git init en la carpeta de la Plataforma después de crear un .gitignore completo (sección 4).
  2. Revisa con git status que .env, instance/ y venv/ no aparezcan. Si alguno ya estaba en un commit, cambia las claves que contenía.
  3. Organiza el trabajo pendiente en ramas (mejora-api, correccion-admin…) y fusiónalas cuando funcionen.
  4. Sube el proyecto a GitHub y pide a un compañero que haga fork, clone, ejecute y proponga una mejora con pull request.
  5. Completa el README.md final.

Entregables

  1. El repositorio en GitHub con: código, .gitignore, .env.ejemplo, requirements.txt, README.md, ESTILO.md, API.md, CREDITOS.md y cuaderno_errores.md.
  2. Un informe de pruebas con los casos de abajo y sus resultados (capturas).
  3. El gráfico de Network de GitHub con al menos dos ramas fusionadas y un pull request.
  4. Una demostración de 7 minutos: registrarse, inscribirse a una actividad, comentar una noticia, entrar como coordinador y crear una actividad, consultar la API con Python y explicar una decisión de seguridad.

Casos de prueba mínimos

# Caso Resultado esperado
1 Reiniciar el servidor Noticias, actividades, usuarios e inscripciones siguen ahí
2 Registro con correo repetido Mensaje flash; no se duplica
3 Visitante anónimo en una ruta de coordinador 403 (no 500)
4 Miembro intenta crear una actividad 403
5 Comentario con <script> Se guarda sin el script
6 DELETE /api/actividades/1 sin clave 401 o 403 (según API.md)
7 GET /api/actividades/9999 404 en JSON
8 Formulario de contacto con tildes Llega al servidor de correo local sin errores
9 375 px de ancho Menú hamburguesa y sin desplazamiento horizontal
10 git log --all -- .env Sin resultados
11 Un compañero clona y ejecuta con el README Funciona en menos de 15 minutos

Criterios técnicos de funcionamiento

Criterio Nivel básico Nivel alto
Rutas y formularios Las páginas y formularios funcionan Validación en el servidor, POST/Redirect/GET, mensajes claros, sin errores 500
Base de datos Guarda y lee los datos Relaciones bien definidas, get_or_404, manejo de IntegrityError
Seguridad Contraseñas con hash Roles con 403 correctos, CSRF, HTML limpiado, secretos fuera del código y del historial
API Devuelve JSON Verbos y códigos correctos, autenticación por cabecera, documentación y pruebas automáticas
Diseño y accesibilidad Usa Bootstrap Guía de estilo aplicada, contraste medido, prueba con usuarios documentada
Control de versiones El código está en GitHub Historial claro, ramas, pull request revisado, README con el que otro puede ejecutar el proyecto
Proceso Entrega el proyecto Cuaderno de errores con al menos 12 entradas del bloque

Posibles extensiones

  • Despliegue en un servidor de Internet con una base de datos PostgreSQL (Día 71 del curso).
  • Migraciones con Flask-Migrate en lugar de borrar la base de datos al cambiar el esquema.
  • Notificaciones por correo a los inscritos un día antes de cada actividad (tarea programada).
  • Estadísticas de participación con pandas y gráficos (bloque de ciencia de datos, Días 72 en adelante).

11. 🧩 Comprueba lo aprendido

Conceptuales

  1. Nombra las tres áreas de Git en tu computador y el comando que mueve los cambios de una a otra.
  2. ¿Para qué sirve el área de preparación?
  3. ¿Qué diferencia hay entre clonar y hacer fork?
  4. ¿Por qué se llama pull request y no push request?
  5. Si subiste una clave a GitHub y luego la agregaste a .gitignore, ¿estás a salvo? ¿Qué debes hacer?

Análisis de código

Terminal
git branch
#   alien-plot
# * main
git merge alien-plot

¿En qué rama estás? ¿Qué cambios entran y a dónde?

Predicción

Creas secretos.txt, haces git add . y git commit, y después escribes secretos.txt en .gitignore. ¿Qué muestra git status? ¿Y git ls-files?

Depuración

"Hago git push -u origin main y me sale src refspec main does not match any". Da dos causas posibles y la solución de cada una.

Modificación

Cambia el .gitignore de la sección 4 para que sí se suba una base de datos de ejemplo datos_ejemplo.db, pero no las demás. (Pista: las reglas que empiezan por ! son excepciones.)

Creación

Escribe la secuencia de comandos para: crear una rama api-v2, hacer dos commits en ella, volver a main, fusionarla y subir todo a GitHub.


12. 🤖 Programar con apoyo de IA

Ciclo de trabajo: formula el problema → inténtalo tú → consulta a la IA → lee y entiende → prueba → compara con la documentación oficial → modifica → explica con tus palabras.

Actividad 1 — Mensajes de commit. Pide a una IA que sugiera un mensaje para un cambio tuyo (muéstrale el git diff). ¿Describe lo que realmente cambió? ¿Está en tiempo presente? Corrígelo si inventa algo.

Actividad 2 — Comandos peligrosos. Pregunta a una IA cómo "borrar el último commit". Si te propone git reset --hard o git push --force, averigua en la documentación de Git qué hacen y en qué casos pierdes trabajo. Anota una alternativa segura (git revert).

Actividad 3 — .gitignore para tu proyecto. Pide a una IA un .gitignore para Flask con SQLite. Compáralo con la plantilla oficial de Python del repositorio github/gitignore y con la sección 4. ¿Incluye .env e instance/?


13. 🛠️ Correcciones técnicas al material original

Archivo Afirmación o comportamiento del curso Observación Tratamiento
505 git push -u origin main Sin configurar init.defaultBranch, Git 2.55 crea master y el push falla (verificado) Secciones 0 y 3
505 Subir a GitHub desde la terminal GitHub no acepta contraseñas en la terminal desde 2021; se usa Credential Manager, token o SSH Nota técnica de la sección 3
504 Primer commit Hace falta configurar user.name y user.email; el correo queda público Secciones 0 y 3
504, 508 git checkout archivo y git checkout rama Siguen funcionando; Git ofrece git restore y git switch, más claros (verificado restore) Nota técnica de la sección 2
508 Salir de Vim con :q! "para guardar y salir" :q! sale sin guardar; funciona porque Git ya puso un mensaje por defecto Nota técnica de la sección 6
506 .gitignore protege los secretos Solo si se configura antes; un archivo ya confirmado sigue en el historial (verificado) Sección 4
506 Ejemplo de .DS_Store (Mac) En Windows, el equivalente es Thumbs.db/desktop.ini; para Flask hay que ignorar también .env e instance/ Sección 4
507 Clonar y ejecutar QuakeJS Requiere Node.js y npm, no vistos en el curso Sección 5
502 Instalar Git con las opciones por defecto El instalador también pregunta el nombre de la rama por defecto y el editor Sección 0

14. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Terminal de VS Code o PyCharm, Git Bash en Windows 501 Sección 0 — Configuración inicial de Git Secciones 8 y 10
Instalar Git para Windows, perfil por defecto de VS Code 502 Sección 0 Instalación init.defaultBranch, editor Secciones 8 y 10
Control de versiones, puntos de guardado, comparar y volver 503 Sección 1 — Del caos de copias al historial Sección 8
Story, git init, .git, status, add, área de preparación, commit -m, tiempo presente, log, hash, HEAD, add ., diff, checkout 504 Sección 2 Repositorio Story restore; retos 1–4 de la sección 2 Secciones 8, 9 y 10
Cuenta de GitHub, nuevo repositorio, público o privado, código abierto, remote add origin, push -u origin main, rama principal, Network 505 Sección 3 Subir Story a GitHub Autenticación, privacidad, errores de push Secciones 8, 9 y 10
.gitignore, secretos, AWS, .DS_Store, git rm --cached -r ., comentarios, comodines, plantillas de github/gitignore, dónde poner las claves 506 Sección 4 Proyecto Project .gitignore para Flask; secretos ya subidos Secciones 9 y 10
git clone, autoalojados, QuakeJS, Wordle en Python, código abierto, awesome-for-beginners 507 Sección 5 Clonar y ejecutar Clonar con criterio; retos 1–3 Sección 9
Ramas, experimento, branch, checkout, alien-plot, merge, Vim, Network 508 Sección 6 Rama alien-plot Conflictos, switch; retos 1–4 Secciones 8 y 10
learngitbranching.js.org 509 Sección 6 Reto opcional Reto 4 de la sección 6 —
Fork, pull request, permisos de escritura, Bangela y Gilfoyle, revisar y fusionar, Alamofire, red social de programadores 510 Sección 7 Fork y pull request de Story Un buen pull request; retos 1–3 Secciones 8 y 10
(No existe en el curso original) — — — Portafolio del bloque en GitHub Sección 9
(No existe en el curso original) — — — Plataforma del Club: proyecto integrador final Sección 10

15. 📦 Evidencias de aprendizaje del Día 70

  • La historia colaborativa en GitHub con su gráfico de Network, un conflicto resuelto y dos pull requests.
  • Tu configuración de Git (git config --global --list, sin mostrar datos privados).
  • El portafolio del bloque (proyecto extra) con tres repositorios y el README de perfil.
  • La Plataforma del Club con todos sus entregables y la demostración.
  • Cuaderno de errores: not a git repository, identidad sin configurar, master contra main, contraseña rechazada por GitHub, remote origin already exists, push rechazado, .gitignore que no funciona por archivos ya rastreados, secretos en el historial, salir de Vim, conflictos de fusión.