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).
32 min de lectura
17 secciones
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 commitsigue 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.
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:
Descargar Git para Windows (Git SCM) y abrir el instalador.
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").
Comprobarlo en VS Code: Terminal → Nueva terminal, y en el menú junto al "+", elegir Git Bash (aparece un signo $).
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
1234
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 maingit 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.
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.
¿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).
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
1234
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.
🟢 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 doscommits 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.
Un repositorio remoto está alojado en el servidor de otra persona, como GitHub. Crear una cuenta es gratis (solo hay que confirmar el correo).
En GitHub, "+" → New repository, nombre "Story" y una descripción ("Mi obra maestra").
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".
Sin README por ahora → Create repository.
Con las instrucciones de línea de comandos, subir el repositorio local existente:
Terminal
12
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.
-uvincula 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.
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.
🛠️ 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
12
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.
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:
Crear el archivo .gitignore (con el punto; el nombre exacto importa).
Si ya agregaste todo al área de preparación, deshacerlo con git rm --cached -r ..
En .gitignore, un nombre de archivo por línea (.DS_Store, secrets.txt); # para comentarios; comodines como *.txt.
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
1234567891011121314151617181920
# 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:
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.
Deja de rastrear el archivo (git rm --cached .env) y agrégalo a .gitignore.
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.
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).
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.
🟢 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ó.
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
123456789101112
git branch alien-plot # crea la ramagit branch # lista las ramas; * marca la actualgit checkout alien-plot # cambia a la rama# ...cambios en los capítulos 1 y 2...gitadd.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...gitadd.git commit -m"Add chapter 4"git merge alien-plot # desde main, trae los cambios de la ramagit 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.
🛠️ 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
12345
<<<<<<< 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.
🟢 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.
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.
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.
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.
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.
cd Documentos
git init
gitadd.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.
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.
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.
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.
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.
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.
Formularios (Días 60 a 62): contacto con correo al servidor local (EmailMessage); inscripciones con Flask-WTF y validadores; POST/Redirect/GET.
Base de datos (Días 63 y 64): modelos Usuario, Noticia, Actividad, Comentario e inscripciones (muchos-a-muchos); CRUD completo.
Contenido (Día 67): noticias con editor enriquecido y HTML limpiado con nh3; una plantilla para crear y editar; borrado con POST.
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.
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.
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.
El repositorio en GitHub con: código, .gitignore, .env.ejemplo, requirements.txt, README.md, ESTILO.md, API.md, CREDITOS.md y cuaderno_errores.md.
Un informe de pruebas con los casos de abajo y sus resultados (capturas).
El gráfico de Network de GitHub con al menos dos ramas fusionadas y un pull request.
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.
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.)
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/?
15
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
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.