Un recetario para GitHub Flow adaptado a dispositivos móviles - integración continua en main, ramas de release para trenes de store, y ramas hotfix paralelas a canales OTA de modo que el JavaScript de production y los binarios de store en vivo permanezcan alineados.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
GitHub Flow (adaptación móvil) 1. Rama desde main → feat/SHIP-220-dark-mode 2. Abre PR → CI + evidencia de dispositivo requerida 3. Fusiona a main → squash preferido 4. Despliega → OTA a canal preview O tag para compilación de store
# Hotfix para versión de store en vivo 2.4.x (paralelo a 2.5 RC en release/2.5.0)git fetch --tagsgit checkout -b hotfix/2.4.2 v2.4.1git cherry-pick <fix-sha>git tag -a v2.4.2 -m "Hotfix: crash on cold start [SHIP-991]"git push origin hotfix/2.4.2 v2.4.2
# Hotfix solo de JS en el mismo runtimeVersion - OTA desde rama hotfixgit checkout hotfix/2.4.2eas update --branch production --channel production --environment production \ --message "hotfix: cold start crash [SHIP-991]"
Ejemplo de carriles paralelos main ← integración release/2.5.0 ← RC en revisión de TestFlight hotfix/2.4.2 ← usuarios de store 2.4.x en production (OTA production channel ← hotfix/2.4.2 commits only)
Cuándo usar esto:
Usuarios en dos versiones de store simultáneamente (retraso de lanzamiento gradual).
OTA production channel no debe recibir commits destinados a la próxima versión de store.
El equipo crece más allá de "etiqueta todo desde main" pero no quiere GitFlow develop.
Se necesita hotfix mientras release/2.5.0 está congelado en App Review.
Cuándo evitar:
Una sola versión en el mercado, OTA deshabilitado - un trunk más simple + tags pueden ser suficientes.
Hotfix requiere un nuevo módulo nativo - debe ser compilación de store, no solo carril OTA.
Escenario:v2.4.1 está en vivo en production (50% lanzamiento de Play). release/2.5.0 espera en App Review. Un crash en arranque en frío afecta solo a usuarios de 2.4.x.
Paso 1 - Mapear ramas Git a canales EAS
<!-- docs/branch-channel-map.md -->| Rama Git | Versión de Store | Rama EAS Update | Canal EAS ||------------------|------------------|-----------------|--------------|| main | (siguiente) | preview | preview || release/2.5.0 | 2.5.0 RC | staging | staging || hotfix/2.4.2 | 2.4.2 en vivo | production | production |
eas channel:view production# Confirma que el canal apunta a la rama production - no a main
Paso 2 - Aterrizar fix en main primero (verdad de integración)
git checkout main && git pull --ff-onlygit checkout -b fix/SHIP-991-cold-start# ... fix ...git commit -m "fix(app): guard null session on cold start [SHIP-991]"git push -u origin fix/SHIP-991-cold-start# PR → squash merge a main
Paso 3 - Abrir rama hotfix desde tag en vivo
git fetch --tagsgit checkout -b hotfix/2.4.2 v2.4.1git cherry-pick <squashed-sha-from-main>npm run typecheck && npm run test -- --cigit push -u origin hotfix/2.4.2
Rama desde tagv2.4.1, no desde main - garantiza el mismo runtimeVersion y código nativo
Cherry-pick un commit - no git merge main
Paso 4 - Envío de store para hotfix nativo (si se requiere)
# Incrementa versión de app solo en rama hotfix# app.json → version 2.4.2, ios.buildNumber++, android.versionCode++git commit -am "chore(release): bump to 2.4.2 [SHIP-991]"git tag -a v2.4.2 -m "Hotfix 2.4.2 - build_id xyz789"git push origin hotfix/2.4.2 v2.4.2
OTA desde main mientras 2.4 y 2.5 difieren en código nativo - El binario 2.5 puede cargar JS incompatible. Fix: Publica OTA de production solo desde hotfix/* atado al runtimeVersion en vivo.
Rama hotfix desde release/2.5.0 para usuarios de 2.4 - Línea base nativa incorrecta. Fix:git checkout -b hotfix/2.4.2 v2.4.1.
Olvidar cherry-pick a release/2.5.0 - Fix se envía solo a usuarios antiguos; 2.5 regresa. Fix: Lista de verificación de retroporte en plantilla de PR.
Eliminar rama hotfix antes de reapuntar canal - Canal de production huérfano. Fix:eas channel:edit solo después de rama de tag nueva documentada.
Hotfixes paralelos de misma versión - Segunda rama desde tag incorrecto. Fix: Tags secuenciales v2.4.2, v2.4.3; un hotfix abierto a la vez por major.minor.
Para aplicaciones pequeñas con envío de store continuo - a menudo sí. Agrega release/* cuando ventanas de revisión, RC soak, o versiones paralelas exigen una rama candidata congelada.
¿Cuántas ramas hotfix pueden estar abiertas?
Una por menor de store en vivo (e.g. un carril hotfix/2.4.x). Múltiples patches se encadenan como v2.4.2, v2.4.3. Una hotfix/2.3.x separada solo si aún apoyas esa cohorte.
¿El hotfix se fusiona a main o solo cherry-pick?
El fix aterriza en main via PR normal primero. Rama hotfix cherry-picks ese SHA - nunca fusiona hotfix → main (trae ruido de bump de versión hacia atrás).
¿Quién es dueño de las publicaciones OTA de production?
CI en tag o release manager con EXPO_TOKEN - no desarrolladores de características desde laptops. Coincide con la política de Release Train Calendar.
¿Qué si hotfix necesita código nativo?
Compilación de store desde hotfix/*, nuevo tag, envío expedido - OTA solo es insuficiente. Incrementa runtimeVersion si cambios de ABI nativo (Runtime Version Policy).