Saltar al contenido

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 localmente
2mkdir datapulse-analitica
3cd datapulse-analitica
4git init
5
6# Crear la estructura del repo de analitica
7mkdir queries informes docs
8touch 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 Analytics
2
3# Credenciales
4.env
5
6# Datos locales (pesan y cambian cada dia)
7*.csv
8*.xlsx
9*.parquet
10
11# Python
12__pycache__/
13*.pyc
14.venv/
15
16# Notebooks
17.ipynb_checkpoints/
18
19# Sistema
20.DS_Store
21Thumbs.db

.gitignore — lo que nunca sube al repo

1-- queries/cohortes_retencion.sql
2-- Analisis de retencion por cohorte mensual
3
4SELECT
5 DATE_TRUNC('month', fecha_registro) AS cohorte,
6 COUNT(DISTINCT user_id) AS usuarios_registro
7FROM usuarios
8GROUP BY 1
9ORDER BY 1;

queries/cohortes_retencion.sql — la query base del equipo

1# informes/kpis_semanales.py
2# Script que genera el informe semanal de KPIs
3# Se ejecuta cada lunes a las 7:00
4
5def 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 kpis
15
16def 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)
22
23if __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 GitHub
2git add .
3git commit -m "feat: estructura inicial del repo de analitica"
4
5# Crear repo en GitHub (con GitHub CLI)
6gh repo create datapulse-analitica --private --source=. --push
7
8# O manualmente:
9# 1. Crear repo en github.com (privado)
10# 2. git remote add origin https://github.com/TU-USUARIO/datapulse-analitica.git
11# 3. git push -u origin main

Commit inicial y subir a GitHub

### El plan: 3 analistas, 3 branches, 1 repo

Cada analista trabaja en su branch. Al final, se fusionan una a una a main.

### 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 branch
2git switch -c feature/cohortes-retencion-producto

Sara crea su feature branch

1-- queries/cohortes_retencion.sql (version ampliada por Sara)
2-- Stakeholder: directora de producto
3
4WITH cohortes AS (
5 SELECT user_id, DATE_TRUNC('month', fecha_registro) AS cohorte
6 FROM usuarios
7),
8actividad AS (
9 SELECT user_id, DATE_TRUNC('month', fecha_evento) AS mes_actividad
10 FROM eventos
11 WHERE tipo_evento = 'login'
12)
13SELECT
14 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), 1
20 ) AS pct_retencion
21FROM cohortes c
22JOIN actividad a ON c.user_id = a.user_id
23WHERE a.mes_actividad >= c.cohorte
24GROUP BY c.cohorte, a.mes_actividad
25ORDER BY c.cohorte, a.mes_actividad;

Sara amplía la query para calcular retención mes a mes

1# Sara commitea y sube
2git add queries/cohortes_retencion.sql
3git commit -m "feat: retencion por cohorte con porcentaje mensual"
4git push -u origin feature/cohortes-retencion-producto
5
6# Sara crea el PR
7gh 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 branch
2git switch main
3git switch -c fix/churn-informe-mensual

Miguel crea su branch para el fix

1# informes/kpis_semanales.py (version de Miguel)
2
3def 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 trials
9 "nps": 72,
10 }
11 return kpis
12
13def 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 = 8500
19 bajas_mes = 178 # Solo clientes de pago que cancelaron
20 if not excluir_trials:
21 bajas_mes = 285 # Incluiria trials (INCORRECTO)
22 return round(bajas_mes / clientes_inicio, 4)
23
24def 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)
30
31if __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 sube
2git add informes/kpis_semanales.py
3git commit -m "fix: excluir trials del calculo de churn mensual"
4git push -u origin fix/churn-informe-mensual
5
6gh 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 --squash
3gh pr merge 2 --squash
4
5# Actualizar main local
6git switch main
7git 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 demas
2git switch main
3git switch -c feature/grafico-conversion-kpis

Tu creas tu branch de trabajo

1# Tu version de informes/kpis_semanales.py
2# Anades calcular_conversion() pero tienes el churn VIEJO (0.034)
3
4def calcular_kpis(semana):
5 kpis = {
6 "usuarios_activos": 12450,
7 "ingresos_eur": 89200,
8 "churn_rate": 0.034, # Valor viejo, sin el fix de Miguel
9 "nps": 72,
10 }
11 return kpis
12
13def calcular_conversion(semana):
14 """Tasa de conversion semanal = compradores / visitantes."""
15 visitantes = 45000
16 compradores = 1890
17 return round(compradores / visitantes, 4)
18
19def generar_informe(kpis):
20 lineas = []
21 for nombre, valor in kpis.items():
22 lineas.append(f" {nombre}: {valor}")
23 return "\n".join(lineas)
24
25if __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 subes
2git add informes/kpis_semanales.py
3git 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 branch
2git switch main
3git pull
4git switch feature/grafico-conversion-kpis
5git merge main
6# 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 Miguel
3# - Mantienes calcular_conversion() tuya
4# - Usas el churn corregido (0.021)
5# - Borras las marcas de conflicto
6
7git add informes/kpis_semanales.py
8git commit -m "merge: resolver conflicto con fix de churn"
9git push
10
11# Ahora tu PR se puede fusionar
12gh 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 final
2git switch main
3git pull
4
5git log --oneline
6# 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 analitica
10
11# Limpiar branches
12git branch -d feature/cohortes-retencion-producto
13git branch -d fix/churn-informe-mensual
14git branch -d feature/grafico-conversion-kpis
15git fetch --prune
16
17# Solo queda main
18git branch
19# * main

Historial limpio y branches borradas

Un historial buscable, legible y profesional.

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

  1. 01.Crear repo con estructura de analítica (queries/, informes/, docs/)
  2. 02.Configurar .gitignore para excluir datos, credenciales y cache
  3. 03.Tres branches en paralelo simulando tres analistas
  4. 04.PRs con descripción profesional (quién lo pidió, qué pregunta responde)
  5. 05.Merge sin conflicto cuando se tocan ficheros distintos
  6. 06.Conflicto real cuando dos personas tocan el mismo fichero
  7. 07.Resolución manteniendo ambas mejoras
  8. 08.Historial limpio gracias a squash merge
  9. 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...