lección 8
Proyecto: colaborar en un repo de analítica como en una empresa
Pon todo en práctica: crea un repo de analítica, simula un equipo con múltiples branches, crea PRs y resuelve conflictos. Tu primera experiencia profesional con Git.
⏱ 55 min
Tu primer día en DataPulse Analytics. Abres Slack y el tech lead te dice: 'clona el repo, mira la estructura, y crea una branch para tu primera tarea.' Ya sabes cada uno de esos comandos por separado — ahora vas a encadenarlos en el mismo flujo que usa un equipo profesional de datos cada día. El escenario: tres analistas, tres tareas, un repo compartido, y un conflicto que resolver.
El escenario: trabajas en DataPulse Analytics, el equipo de analítica de un e-commerce de moda. Sois 3 analistas que compartís un repositorio con queries SQL, scripts de informes y documentación. Hay 3 tareas pendientes en el sprint: Sara trabaja en un análisis de cohortes para la directora de producto, Miguel corrige un error en el cálculo del churn del informe mensual, y tú añades un nuevo gráfico al notebook de KPIs semanales. Vas a ser los 3, cada uno en su branch.
### Paso 1: Crear el repo del equipo
1# Crear el proyecto localmente2mkdir datapulse-analitica3cd datapulse-analitica4git init56# Crear la estructura del repo de analitica7mkdir queries informes docs8touch queries/cohortes_retencion.sql informes/kpis_semanales.py docs/diccionario_metricas.md .gitignore README.md
Estructura del repo de DataPulse Analytics
Ahora vamos a darle contenido a los archivos base. Empezamos por el .gitignore:
1# .gitignore de DataPulse Analytics23# Credenciales4.env56# Datos locales (pesan y cambian cada dia)7*.csv8*.xlsx9*.parquet1011# Python12__pycache__/13*.pyc14.venv/1516# Notebooks17.ipynb_checkpoints/1819# Sistema20.DS_Store21Thumbs.db
.gitignore — lo que nunca sube al repo
1-- queries/cohortes_retencion.sql2-- Analisis de retencion por cohorte mensual34SELECT5 DATE_TRUNC('month', fecha_registro) AS cohorte,6 COUNT(DISTINCT user_id) AS usuarios_registro7FROM usuarios8GROUP BY 19ORDER BY 1;
queries/cohortes_retencion.sql — la query base del equipo
1# informes/kpis_semanales.py2# Script que genera el informe semanal de KPIs3# Se ejecuta cada lunes a las 7:0045def calcular_kpis(semana):6 """Calcula los KPIs principales de la semana."""7 print(f"Generando KPIs para semana: {semana}")8 kpis = {9 "usuarios_activos": 12450,10 "ingresos_eur": 89200,11 "churn_rate": 0.034,12 "nps": 72,13 }14 return kpis1516def generar_informe(kpis):17 """Formatea los KPIs para el email semanal."""18 lineas = []19 for nombre, valor in kpis.items():20 lineas.append(f" {nombre}: {valor}")21 return "\n".join(lineas)2223if __name__ == "__main__":24 kpis = calcular_kpis("2024-W28")25 print(generar_informe(kpis))
informes/kpis_semanales.py — el script que alimenta el informe del lunes
1# Commit inicial y subir a GitHub2git add .3git commit -m "feat: estructura inicial del repo de analitica"45# Crear repo en GitHub (con GitHub CLI)6gh repo create datapulse-analitica --private --source=. --push78# O manualmente:9# 1. Crear repo en github.com (privado)10# 2. git remote add origin https://github.com/TU-USUARIO/datapulse-analitica.git11# 3. git push -u origin main
Commit inicial y subir a GitHub
### El plan: 3 analistas, 3 branches, 1 repo
### Paso 2: Sara amplía el análisis de cohortes
Eres Sara. La directora de producto quiere saber si los usuarios que se registraron después del rediseño de la app retienen mejor que los anteriores. Creas tu branch y amplías la query de cohortes:
1# Sara crea su branch2git switch -c feature/cohortes-retencion-producto
Sara crea su feature branch
1-- queries/cohortes_retencion.sql (version ampliada por Sara)2-- Stakeholder: directora de producto34WITH cohortes AS (5 SELECT user_id, DATE_TRUNC('month', fecha_registro) AS cohorte6 FROM usuarios7),8actividad AS (9 SELECT user_id, DATE_TRUNC('month', fecha_evento) AS mes_actividad10 FROM eventos11 WHERE tipo_evento = 'login'12)13SELECT14 c.cohorte,15 a.mes_actividad,16 COUNT(DISTINCT c.user_id) AS usuarios_activos,17 ROUND(18 COUNT(DISTINCT c.user_id) * 100.0 /19 MAX(COUNT(DISTINCT c.user_id)) OVER (PARTITION BY c.cohorte), 120 ) AS pct_retencion21FROM cohortes c22JOIN actividad a ON c.user_id = a.user_id23WHERE a.mes_actividad >= c.cohorte24GROUP BY c.cohorte, a.mes_actividad25ORDER BY c.cohorte, a.mes_actividad;
Sara amplía la query para calcular retención mes a mes
1# Sara commitea y sube2git add queries/cohortes_retencion.sql3git commit -m "feat: retencion por cohorte con porcentaje mensual"4git push -u origin feature/cohortes-retencion-producto56# Sara crea el PR7gh pr create --title "feat: retencion por cohorte para producto" \8 --body "Calcula pct de retencion mes a mes. Para directora de producto."
Sara sube su branch y crea PR
### Paso 3: Miguel corrige el cálculo del churn
Eres Miguel. El informe mensual muestra un churn (tasa de bajas) del 2.85%, pero descubres que cuenta como "baja" a usuarios en periodo de prueba gratuito que nunca pagaron. El CEO toma decisiones con un número inflado. Corriges el bug:
1# Miguel vuelve a main y crea su branch2git switch main3git switch -c fix/churn-informe-mensual
Miguel crea su branch para el fix
1# informes/kpis_semanales.py (version de Miguel)23def calcular_kpis(semana):4 """Calcula los KPIs principales de la semana."""5 kpis = {6 "usuarios_activos": 12450,7 "ingresos_eur": 89200,8 "churn_rate": 0.021, # CORREGIDO: excluir trials9 "nps": 72,10 }11 return kpis1213def calcular_churn(mes, excluir_trials=True):14 """Calcula el churn rate mensual.15 Los usuarios en prueba gratuita que no convierten NO son bajas.16 Solo contamos como baja a quien ERA cliente de pago y dejo de serlo.17 """18 clientes_inicio = 850019 bajas_mes = 178 # Solo clientes de pago que cancelaron20 if not excluir_trials:21 bajas_mes = 285 # Incluiria trials (INCORRECTO)22 return round(bajas_mes / clientes_inicio, 4)2324def generar_informe(kpis):25 """Formatea los KPIs para el email semanal."""26 lineas = []27 for nombre, valor in kpis.items():28 lineas.append(f" {nombre}: {valor}")29 return "\n".join(lineas)3031if __name__ == "__main__":32 kpis = calcular_kpis("2024-W28")33 kpis["churn_rate"] = calcular_churn("2024-07")34 print(generar_informe(kpis))
Miguel corrige el cálculo del churn excluyendo trials
1# Miguel commitea y sube2git add informes/kpis_semanales.py3git commit -m "fix: excluir trials del calculo de churn mensual"4git push -u origin fix/churn-informe-mensual56gh pr create --title "fix: churn inflado por incluir trials" \7 --body "El CEO veia 2.85% cuando el real es 2.09%. Excluye trials."
Miguel sube su fix y crea PR
### Paso 4: Fusionar los dos primeros PRs
Sara tocó queries/cohortes_retencion.sql y Miguel tocó informes/kpis_semanales.py. Ficheros distintos: no hay conflicto entre ellos. Fusionamos ambos:
1# Fusionar ambos PRs (no conflictan entre si)2gh pr merge 1 --squash3gh pr merge 2 --squash45# Actualizar main local6git switch main7git pull
Fusionar los dos primeros PRs sin conflicto
### Paso 5: Tu branch y el conflicto
Ahora eres tú. Tu tarea: añadir una función de conversión al script de KPIs. Creaste tu branch el mismo día que Sara y Miguel (antes de sus merges), así que tu versión del fichero NO tiene el fix de Miguel:
1# Tu creaste tu branch al mismo tiempo que los demas2git switch main3git switch -c feature/grafico-conversion-kpis
Tu creas tu branch de trabajo
1# Tu version de informes/kpis_semanales.py2# Anades calcular_conversion() pero tienes el churn VIEJO (0.034)34def calcular_kpis(semana):5 kpis = {6 "usuarios_activos": 12450,7 "ingresos_eur": 89200,8 "churn_rate": 0.034, # Valor viejo, sin el fix de Miguel9 "nps": 72,10 }11 return kpis1213def calcular_conversion(semana):14 """Tasa de conversion semanal = compradores / visitantes."""15 visitantes = 4500016 compradores = 189017 return round(compradores / visitantes, 4)1819def generar_informe(kpis):20 lineas = []21 for nombre, valor in kpis.items():22 lineas.append(f" {nombre}: {valor}")23 return "\n".join(lineas)2425if __name__ == "__main__":26 kpis = calcular_kpis("2024-W28")27 kpis["conversion_rate"] = calcular_conversion("2024-W28")28 print(generar_informe(kpis))
Tú añades calcular_conversion() pero con el churn viejo
1# Commiteas y subes2git add informes/kpis_semanales.py3git commit -m "feat: funcion de conversion semanal para KPIs"4git push -u origin feature/grafico-conversion-kpis
Subes tu branch
Ahora actualizas tu branch con lo último de main (que ya tiene el fix de Miguel):
1# Traes lo ultimo de main a tu branch2git switch main3git pull4git switch feature/grafico-conversion-kpis5git merge main6# CONFLICTO en informes/kpis_semanales.py!7# Git no puede decidir: tu churn (0.034) o el de Miguel (0.021)?
El conflicto aparece al traer los cambios de Miguel
Resuelves el conflicto manteniendo AMBAS mejoras: el churn corregido de Miguel Y tu función de conversión nueva:
1# Despues de resolver el conflicto manualmente:2# - Mantienes calcular_churn() de Miguel3# - Mantienes calcular_conversion() tuya4# - Usas el churn corregido (0.021)5# - Borras las marcas de conflicto67git add informes/kpis_semanales.py8git commit -m "merge: resolver conflicto con fix de churn"9git push1011# Ahora tu PR se puede fusionar12gh pr create --title "feat: tasa de conversion en KPIs semanales" \13 --body "Anade calcular_conversion(). Resuelve conflicto con fix de churn."14gh pr merge 3 --squash
Resolver el conflicto y completar el merge
Consejo de senior: cuando resuelvas un conflicto, SIEMPRE quédate con ambas mejoras a menos que una contradiga a la otra. El fix de Miguel y tu feature son complementarios. Si te quedaras solo con tu versión, perderías el fix del churn y el CEO volvería a ver números inflados.
### Paso 6: Resultado final y limpieza
1# Ver el historial final2git switch main3git pull45git log --oneline6# abc1234 feat: tasa de conversion en KPIs semanales (#3)7# def5678 fix: churn inflado por incluir trials (#2)8# ghi9012 feat: retencion por cohorte para producto (#1)9# xyz0000 feat: estructura inicial del repo de analitica1011# Limpiar branches12git branch -d feature/cohortes-retencion-producto13git branch -d fix/churn-informe-mensual14git branch -d feature/grafico-conversion-kpis15git fetch --prune1617# Solo queda main18git branch19# * main
Historial limpio y branches borradas
Esto te lo van a preguntar en la entrevista: "cuéntame una vez que tuviste un conflicto en Git y cómo lo resolviste". La respuesta buena: "dos compañeros y yo tocamos el mismo archivo. Actualicé mi branch con main, vi el conflicto, mantuve ambas mejoras, lo marqué como resuelto y subí. El revisor confirmó que ambas cosas funcionaban juntas." Eso demuestra que entiendes el flujo.
### Recapitulacion
- 01.Crear repo con estructura de analítica (queries/, informes/, docs/)
- 02.Configurar .gitignore para excluir datos, credenciales y cache
- 03.Tres branches en paralelo simulando tres analistas
- 04.PRs con descripción profesional (quién lo pidió, qué pregunta responde)
- 05.Merge sin conflicto cuando se tocan ficheros distintos
- 06.Conflicto real cuando dos personas tocan el mismo fichero
- 07.Resolución manteniendo ambas mejoras
- 08.Historial limpio gracias a squash merge
- 09.Limpieza de branches al terminar
Consejo de senior: practica este flujo entero al menos tres veces en repos de prueba antes de hacerlo en el repo de tu empresa. La tercera vez ya no necesitarás mirar los comandos.
Ya dominas el trabajo en equipo con Git. Sabes crear branches, resolver conflictos y mantener un historial limpio. Cada vez que abras una branch, estarás protegiendo a tu equipo de errores que nadie ve hasta que es demasiado tarde.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...