Git Workflows: GitFlow vs GitHub Flow vs Trunk-Based vs Release Flow
Resumen
Existen múltiples estrategias de branching Git para gestionar el desarrollo de software: GitFlow (modelo complejo con develop/feature/release/hotfix branches para equipos grandes), GitHub Flow (minimalista con feature branches + main + deploy before merge), GitLab Flow (híbrido con environment branches staging/production para control deployment), Trunk-Based Development (commits directos a main con short-lived branches <24h, usado por Google/Facebook), Release Flow (trunk-based + release branches sin merge back, usado por Microsoft Azure), OneFlow (GitFlow simplificado eliminando develop branch), y Feature Branch Workflow (básico con feature branches + pull requests). Cada estrategia se adapta a diferentes tamaños de equipo, frecuencia de releases, madurez CI/CD y control de environments.
¿Por qué necesitas una estrategia de branching?
Sin estrategia definida surgen problemas:
- Merge hell: Branches long-lived (>2 semanas) generan conflictos masivos al integrar
- Release delays: No hay proceso claro para promocionar código a producción
- Hotfix chaos: Bugs críticos en producción sin workflow para fixes urgentes
- Code quality drift: Sin pull requests, código sin revisar llega a main
- Deployment uncertainty: "¿Qué commits están en producción ahora?"
Una estrategia de branching define:
- Tipos de branches: main/develop/feature/release/hotfix
- Naming conventions:
feature/user-auth,hotfix/sql-injection - Merge strategy: Fast-forward, squash, merge commit
- Review process: Pull requests obligatorios, code owners
- Release cadence: Continuous deployment vs sprint-based releases
Comparativa rápida
| Estrategia | Branches principales | Branches auxiliares | Complejidad | Equipo ideal | Release frequency |
|---|---|---|---|---|---|
| GitFlow | main + develop | feature, release, hotfix | 🔴 Alta | >10 devs, releases planificadas | Mensual/trimestral |
| GitHub Flow | main | feature | 🟢 Baja | 3-10 devs, CD | Diaria/continua |
| GitLab Flow | main | production, staging, feature | 🟡 Media | 5-30 devs, environment-based | Variable por entorno |
| Trunk-Based | main (trunk) | short-lived (<24h) | 🟡 Media | >50 devs, CD maduro | Múltiples/día |
| Release Flow | main | release (long-lived) | 🟡 Media | >100 devs, sprints | Sprint-based (2-3 semanas) |
| OneFlow | main | release, feature, hotfix | 🟡 Media | 10-50 devs | Sprint/mensual |
| Feature Branch | main | feature | 🟢 Baja | <5 devs, flexible | Variable |
GitFlow
Arquitectura GitFlow
gitGraph
commit id: "Initial"
branch develop
checkout develop
commit id: "Setup"
branch feature/login
checkout feature/login
commit id: "Login UI"
commit id: "Auth logic"
checkout develop
merge feature/login
branch feature/dashboard
checkout feature/dashboard
commit id: "Dashboard API"
checkout develop
merge feature/dashboard
branch release/1.0
checkout release/1.0
commit id: "Bump version"
commit id: "Fix RC bug"
checkout main
merge release/1.0 tag: "v1.0.0"
checkout develop
merge release/1.0
checkout main
branch hotfix/security
commit id: "Patch CVE"
checkout main
merge hotfix/security tag: "v1.0.1"
checkout develop
merge hotfix/security
Branches en GitFlow
1. main (producción)
- Código en producción siempre
- Solo merges desde release o hotfix
- Cada merge = tag de versión (v1.0.0, v1.0.1)
2. develop (integración)
- Branch principal de desarrollo
- Developers mergen aquí via pull requests
- Siempre buildable pero no production-ready
3. feature/* (nuevas features)
# Crear feature branch desde develop
git checkout develop
git pull origin develop
git checkout -b feature/user-authentication
# Desarrollo...
git add .
git commit -m "Add JWT token validation"
# Push y crear pull request a develop
git push origin feature/user-authentication
Naming conventions:
feature/user-authenticationfeature/payment-gatewayfeature/JIRA-1234-oauth-integration
Lifetime: 1-2 semanas (idealmente <1 sprint)
4. release/* (preparación release)
# Crear release branch desde develop (fin de sprint)
git checkout develop
git checkout -b release/1.2.0
# Solo bug fixes en release branch
git commit -m "Fix: Update copyright year"
git commit -m "Bump version to 1.2.0"
# Merge a main (producción)
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin main --tags
# Merge back a develop (traer fixes)
git checkout develop
git merge --no-ff release/1.2.0
git push origin develop
# Eliminar release branch
git branch -d release/1.2.0
5. hotfix/* (fixes urgentes producción)
# Crear hotfix desde main (producción rota)
git checkout main
git checkout -b hotfix/sql-injection-cve-2024-1234
# Fix crítico
git commit -m "Fix: Sanitize SQL inputs"
# Merge a main
git checkout main
git merge --no-ff hotfix/sql-injection-cve-2024-1234
git tag -a v1.2.1 -m "Hotfix: SQL injection patch"
git push origin main --tags
# Merge a develop (evitar regresión)
git checkout develop
git merge --no-ff hotfix/sql-injection-cve-2024-1234
git push origin develop
# Si existe release branch activo, merge ahí también
git checkout release/1.3.0
git merge --no-ff hotfix/sql-injection-cve-2024-1234
Configuración GitFlow (Azure DevOps/GitHub)
Branch policies (Azure DevOps):
# Proteger main: solo merges desde release/hotfix
az repos policy merge-strategy create \
--repository-id <REPO_ID> \
--branch main \
--blocking true \
--enabled true \
--use-squash-merge false
# Proteger develop: require pull request + 2 reviewers
az repos policy approver-count create \
--repository-id <REPO_ID> \
--branch develop \
--blocking true \
--enabled true \
--minimum-approver-count 2 \
--creator-vote-counts false
GitHub branch protection (main):
# .github/branch-protection.yml
branches:
main:
protection:
required_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
required_status_checks:
strict: true
contexts:
- "ci/build"
- "ci/tests"
enforce_admins: true
restrictions:
users: []
teams: ["release-managers"]
Ventajas GitFlow
✅ Clara separación producción/desarrollo: main = prod, develop = staging
✅ Soporte múltiples versiones: Mantener v1.x y v2.x simultáneamente
✅ Hotfix process robusto: Pathway claro para emergency fixes
✅ Release candidates: Testing exhaustivo en release branch antes de prod
Desventajas GitFlow
❌ Complejidad alta: 5 tipos de branches, reglas merge complejas
❌ Merge overhead: Hotfix debe mergearse a main + develop + release (si existe)
❌ No apto para CD: Release branch conflicts con continuous deployment
❌ Long-lived branches: Feature branches >2 semanas = merge hell
Cuándo usar GitFlow
- ✅ Equipos >10 developers
- ✅ Releases planificadas (mensual/trimestral)
- ✅ Múltiples versiones en producción (SaaS multi-tenant con versiones legacy)
- ✅ Proceso release riguroso (QA manual extensivo)
- ❌ NO si haces continuous deployment (múltiples deploys/día)
GitHub Flow
Arquitectura GitHub Flow
gitGraph
commit id: "Initial"
commit id: "v1.0.0" tag: "v1.0.0"
branch feature/api-v2
checkout feature/api-v2
commit id: "API schema"
commit id: "Endpoints"
checkout main
commit id: "Hotfix CSS"
checkout feature/api-v2
commit id: "Tests"
checkout main
merge feature/api-v2 id: "Deploy + Merge"
commit id: "v1.1.0" tag: "v1.1.0"
branch feature/websockets
checkout feature/websockets
commit id: "WS server"
commit id: "Client lib"
checkout main
merge feature/websockets id: "Deploy + Merge"
commit id: "v1.2.0" tag: "v1.2.0"
Workflow GitHub Flow
Reglas simples:
- main siempre deployable: Cada commit en main puede ir a producción
- Feature branches desde main:
git checkout -b feature/new-feature - Push regularmente: Backup y feedback temprano
- Pull request para feedback: Antes de merge, discusión + review
- Deploy antes de merge: Testing en staging/producción
- Merge después de aprobar deploy: Si deploy OK → merge PR
Ejemplo práctico
Paso 1: Crear feature branch
git checkout main
git pull origin main
git checkout -b feature/dark-mode
# Desarrollo
git add .
git commit -m "Add dark mode toggle component"
git push origin feature/dark-mode
Paso 2: Abrir pull request
# GitHub CLI
gh pr create \
--title "Feature: Dark mode support" \
--body "Implements dark mode with system preference detection. Closes #456" \
--base main \
--head feature/dark-mode
Paso 3: CI/CD automático (GitHub Actions)
# .github/workflows/pr.yml
name: PR Validation
on:
pull_request:
branches: [main]
jobs:
test-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Deploy to staging
if: success()
run: |
# Deploy PR to unique staging URL
vercel deploy --token=${{ secrets.VERCEL_TOKEN }} \
--env=staging \
--meta="pr=${{ github.event.pull_request.number }}"
- name: Comment staging URL
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 Deployed to staging: https://pr-${{ github.event.pull_request.number }}.staging.example.com'
})
Paso 4: Review + test en staging
# Reviewers prueban en staging URL
# https://pr-123.staging.example.com
# Si hay bugs, push nuevos commits
git commit -m "Fix: Dark mode contrast ratio"
git push origin feature/dark-mode
# CI/CD redeploy automáticamente
Paso 5: Deploy a producción
# Opción A: Deploy manual antes de merge
# Deploy feature branch a producción para validar
vercel deploy --prod --token=$VERCEL_TOKEN
# Si deploy exitoso → merge PR
gh pr merge 123 --squash --delete-branch
Opción B: Auto-deploy post-merge (recomendado)
# .github/workflows/deploy.yml
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to production
run: vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }}
Deploy antes de merge (crítico)
Problema sin pre-deploy: Merge → Deploy → Bug en prod → Rollback urgente
Solución GitHub Flow:
# 1. PR abierto → Deploy automático a staging
https://pr-123.staging.example.com
# 2. Review + QA en staging
# 3. Si staging OK → Deploy a producción (canary/blue-green)
# 4. Si producción OK durante 30min → Merge PR a main
# 5. Si producción falla → NO merge, fix en feature branch
Ventaja: main siempre refleja código en producción (no código "esperando deploy")
Variantes GitHub Flow
1. Squash merge (recomendado)
# Convierte 10 commits en feature branch → 1 commit en main
gh pr merge 123 --squash --delete-branch
# Resultado: Historia main limpia
# main: feat: Add dark mode (PR #123)
# En lugar de:
# - WIP dark mode
# - Fix typo
# - Update tests
# - Fix linter
# ...
2. Merge commit (preserva historia)
3. Rebase (historia lineal)
gh pr merge 123 --rebase
# Replay commits de feature branch sobre main
# Historia lineal sin merge commits
Ventajas GitHub Flow
✅ Simplicidad extrema: Solo main + feature branches
✅ Continuous deployment: Deploy múltiples veces/día sin friction
✅ Fast feedback: Deploy antes de merge = bugs detectados pre-merge
✅ Historia limpia: Squash merge = 1 commit por feature en main
Desventajas GitHub Flow
❌ No release branches: Difícil mantener múltiples versiones (v1.x, v2.x)
❌ Deploy obligatorio: Requiere CI/CD maduro (no manual QA)
❌ Hotfix = feature branch: No distinción entre feature y hotfix
❌ No staging prolongado: Código debe estar production-ready al merge
Cuándo usar GitHub Flow
- ✅ Continuous deployment (múltiples deploys/día)
- ✅ SaaS single-version (todos usuarios misma versión)
- ✅ CI/CD automatizado (tests + deploy automáticos)
- ✅ Equipos pequeños-medios (3-20 devs)
- ❌ NO si necesitas releases planificadas con QA manual extensivo
Trunk-Based Development
Arquitectura Trunk-Based
gitGraph
commit id: "Init"
commit id: "Feature A" tag: "deploy-1"
commit id: "Feature B"
commit id: "Feature C" tag: "deploy-2"
branch short-lived-1
checkout short-lived-1
commit id: "Quick fix"
checkout main
merge short-lived-1
commit id: "Fix merged" tag: "deploy-3"
commit id: "Feature D"
commit id: "Feature E" tag: "deploy-4"
Principios Trunk-Based
1. Commits directos a main (equipos maduros)
# Sin branches: commit directo a trunk
git checkout main
git pull --rebase origin main
# Cambio pequeño (<2h trabajo)
git add .
git commit -m "feat: Add user avatar upload"
git push origin main
# CI/CD deploy automático a producción en <10 min
2. Short-lived branches (<24 horas)
# Para cambios que requieren >2h
git checkout -b quick-fix-validation
# Trabajo durante 4-8 horas
git commit -m "Fix: Email validation regex"
# Merge mismo día (NO pull request largo)
git checkout main
git pull --rebase origin main
git merge quick-fix-validation --ff-only
git push origin main
git branch -d quick-fix-validation
3. Feature flags para features incompletas
// Feature flag: ocultar feature en desarrollo
if (featureFlags.isEnabled('new-checkout-flow')) {
return <NewCheckoutFlow />;
} else {
return <LegacyCheckoutFlow />;
}
# Commit código incomplete a main (con flag disabled)
git commit -m "feat: New checkout flow (behind feature flag)"
git push origin main
# Deploy a producción → feature oculta para usuarios
# Developers pueden testear con flag enabled
# Cuando feature completa → enable flag
featureFlags.enable('new-checkout-flow', { rollout: 10 }); // 10% usuarios
# Gradual rollout: 10% → 50% → 100%
# Eliminar flag cuando 100% estable
git commit -m "refactor: Remove new-checkout-flow feature flag"
Configuración Trunk-Based (Google/Facebook style)
CI/CD ultra-rápido (obligatorio):
# .github/workflows/trunk.yml
name: Trunk CI/CD
on:
push:
branches: [main]
jobs:
test-and-deploy:
runs-on: ubuntu-latest
timeout-minutes: 10 # Forzar tests rápidos
steps:
- uses: actions/checkout@v3
# Parallel test execution
- name: Unit tests
run: npm run test:unit -- --parallel
timeout-minutes: 3
- name: Integration tests
run: npm run test:integration
timeout-minutes: 5
- name: Deploy to production
if: success()
run: |
# Canary deploy (1% traffic)
kubectl set image deployment/app app=myapp:${{ github.sha }}
kubectl rollout status deployment/app
# Monitor metrics 5 min
./scripts/monitor-canary.sh
# If metrics OK → full rollout
kubectl scale deployment/app --replicas=20
Pre-commit hooks (calidad local):
# .husky/pre-commit
#!/bin/bash
npm run lint
npm run test:unit
npm run build
# Si falla → commit bloqueado
Branch protection (permitir solo fast-forward):
# Azure DevOps: Forzar squash/rebase (no merge commits)
az repos policy merge-strategy create \
--repository-id <REPO_ID> \
--branch main \
--blocking true \
--use-squash-merge true
# GitHub: Linear history
gh api repos/:owner/:repo/branches/main/protection \
--method PUT \
--field required_linear_history=true
Scaled Trunk-Based (Google/Facebook >1000 devs)
Monorepo con virtual branches:
# Google: 1 repo gigante, 1 branch (trunk)
# 2+ billion lines of code
# 25,000+ developers
# 40,000+ commits/día
# Bazel: Builds incrementales ultra-rápidos
bazel build //services/search/...
# Solo rebuilds changed dependencies (graph-based)
# Tests afectados solamente
bazel test --test_tag_filters=affected //...
Continuous Integration at Scale:
# 40K commits/día = 1 commit cada 2 segundos
# CI debe ser instantáneo
# Presubmit tests (antes de commit)
- Lint changed files (2 sec)
- Unit tests affected modules (30 sec)
- Build affected targets (1 min)
# Postsubmit tests (después de commit, async)
- Full integration tests (10 min)
- E2E tests (30 min)
- Performance regression tests (1 hour)
# Si postsubmit falla → auto-revert commit
Ventajas Trunk-Based
✅ Merge conflicts mínimos: Branches <24h = pequeños cambios fáciles de integrar
✅ CI/CD velocidad máxima: Deploy múltiples veces/día (hasta 100+/día en Google)
✅ Simplicidad extrema: Solo main branch, no GitFlow mental overhead
✅ Feedback loop ultra-corto: Bug detectado en <10 min (no días)
Desventajas Trunk-Based
❌ Requiere CI/CD maduro: Tests rápidos (<5 min) y confiables (no flaky tests)
❌ Cultura team alta: Disciplina para commits pequeños y frecuentes
❌ Feature flags overhead: Código con if (flag) por todas partes
❌ No releases tradicionales: Difícil hacer "release 2.0 en 3 meses"
Cuándo usar Trunk-Based
- ✅ Equipos muy experimentados (seniors >50%)
- ✅ CI/CD ultra-automatizado (deploy <10 min desde commit)
- ✅ Test coverage alto (>80%) y tests rápidos
- ✅ SaaS continuous deployment (Facebook/Netflix/Google model)
- ❌ NO si equipo junior o CI/CD inmaduro
Release Flow (Microsoft Azure)
Arquitectura Release Flow
gitGraph
commit id: "Sprint 128"
branch users/alice/feature-a
checkout users/alice/feature-a
commit id: "Feature A WIP"
checkout main
merge users/alice/feature-a id: "PR #1234"
branch users/bob/bugfix-b
checkout users/bob/bugfix-b
commit id: "Fix bug B"
checkout main
merge users/bob/bugfix-b id: "PR #1235"
commit id: "End Sprint 129"
branch releases/M129
checkout releases/M129
commit id: "Deploy M129" tag: "v129.0"
checkout main
branch users/carol/feature-c
commit id: "Feature C (Sprint 130)"
checkout main
merge users/carol/feature-c
checkout releases/M129
branch hotfix-from-main
checkout hotfix-from-main
commit id: "Critical fix"
checkout main
merge hotfix-from-main id: "PR #1250"
checkout releases/M129
cherry-pick id: "Critical fix" parent:"Deploy M129"
commit id: "Hotfix M129" tag: "v129.1"
Workflow Release Flow
Desarrollo continuo en main (como Trunk-Based):
# Developer crea topic branch (1-3 días)
git checkout -b users/alice/add-oauth-provider
# Commits frecuentes
git commit -m "Add Google OAuth client ID config"
git commit -m "Implement OAuth callback handler"
git push origin users/alice/add-oauth-provider
# Pull request a main (NO a release branch)
az repos pr create \
--title "Add Google OAuth provider" \
--source-branch users/alice/add-oauth-provider \
--target-branch main \
--reviewers security-team
CI/CD rápido (pre-merge):
# azure-pipelines-pr.yml
trigger: none
pr:
branches:
include:
- main
pool:
vmImage: ubuntu-latest
steps:
# Fast tests (5 min)
- script: npm run test:unit
displayName: Unit tests
- script: npm run test:integration
displayName: Integration tests
timeoutInMinutes: 5
# Build validation
- script: npm run build
displayName: Build
# Policy compliance
- task: ComponentGovernanceComponentDetection@0
displayName: Security scan
Merge a main (squash):
# Auto-complete PR después de approvals
az repos pr update \
--id 1234 \
--auto-complete true \
--squash true \
--delete-source-branch true
# Resultado: 1 commit limpio en main
# "Add Google OAuth provider (#1234)"
Sprint-based releases (cada 3 semanas):
# Fin de Sprint 129 → crear release branch
git checkout main
git pull origin main
git checkout -b releases/M129
# Tag release
git tag -a v129.0 -m "Release Sprint 129"
git push origin releases/M129 --tags
# Deploy release branch a producción (ring-based)
# Ring 0 (internal): 1% → 1 hora monitoring
# Ring 1 (early): 10% → 24 horas monitoring
# Ring 2 (broad): 50% → 48 horas monitoring
# Ring 3 (full): 100% → release completo
Hotfix workflow (fix en main, cherry-pick a release):
# Bug crítico descubierto en producción (releases/M129)
# SIEMPRE fix en main primero (evita regression en M130)
git checkout main
git checkout -b users/alice/hotfix-sql-injection
git commit -m "Fix: Sanitize SQL query parameters"
git push origin users/alice/hotfix-sql-injection
# Pull request a main
az repos pr create \
--title "Hotfix: SQL injection vulnerability" \
--source-branch users/alice/hotfix-sql-injection \
--target-branch main
# Merge a main
az repos pr update --id 1250 --auto-complete true --squash true
# Cherry-pick a release branch (Azure DevOps UI o CLI)
git checkout releases/M129
git cherry-pick <commit-hash-from-main>
git push origin releases/M129
# Tag hotfix
git tag -a v129.1 -m "Hotfix: SQL injection patch"
git push origin releases/M129 --tags
# Deploy v129.1 a producción (fast-track rings)
Release branches nunca merge back a main:
❌ INCORRECTO:
releases/M129 → merge back to main
✅ CORRECTO:
- Hotfix en main → cherry-pick to releases/M129
- releases/M129 es snapshot de main en momento del release
- Next release (M130) branches desde main actualizado
Naming conventions Release Flow
# Topic branches (short-lived, 1-5 días)
users/alice/feature-name
users/bob/bugfix-description
users/carol/refactor-component
# Release branches (long-lived, 3-6 meses)
releases/M129 # Sprint 129
releases/M130 # Sprint 130
# Tags
v129.0 # Release Sprint 129
v129.1 # Hotfix 1 Sprint 129
v130.0 # Release Sprint 130
Branch policies (Azure DevOps)
# Proteger main: require PR + 2 reviewers + CI pass
az repos policy approver-count create \
--branch main \
--repository-id <REPO_ID> \
--blocking true \
--enabled true \
--minimum-approver-count 2 \
--creator-vote-counts false
az repos policy build create \
--branch main \
--repository-id <REPO_ID> \
--blocking true \
--enabled true \
--build-definition-id <BUILD_ID> \
--display-name "PR Validation" \
--queue-on-source-update-only true
# Proteger release branches: solo cherry-picks desde main
az repos policy merge-strategy create \
--branch releases/* \
--repository-id <REPO_ID> \
--blocking true \
--use-squash-merge false \
--allow-no-fast-forward false
Ventajas Release Flow
✅ Trunk-based benefits: CI/CD rápido, merge conflicts mínimos
✅ Sprint-aligned releases: Deploy predecible cada 3 semanas
✅ Hotfix sin bloquear desarrollo: Main sigue abierto durante hotfix
✅ Múltiples releases en prod: Ring-based deployment (Ring 2 en v129, Ring 3 en v130)
✅ Escalable: Microsoft Azure DevOps usa esto con 500+ devs
Desventajas Release Flow
❌ Cherry-pick overhead: Hotfixes deben aplicarse manualmente a release branches
❌ Release branch long-lived: 3-6 meses de support = merge conflicts ocasionales
❌ No apto para continuous deployment puro: Releases cada 3 semanas (no diario)
Cuándo usar Release Flow
- ✅ Equipos grandes (>50 devs)
- ✅ Sprint-based development (Scrum)
- ✅ Releases predecibles (cada 2-4 semanas)
- ✅ Múltiples versiones en producción simultáneamente (rings)
- ✅ CI/CD maduro pero no continuous deployment extremo
GitLab Flow
Arquitectura GitLab Flow (Environment-based)
gitGraph
commit id: "Init"
branch feature/api
checkout feature/api
commit id: "API changes"
checkout main
merge feature/api id: "Merge to main"
branch staging
checkout staging
merge main id: "Deploy to staging"
branch production
checkout production
merge staging id: "Deploy to prod"
checkout main
branch feature/ui
commit id: "UI update"
checkout main
merge feature/ui
checkout staging
merge main id: "Staging update"
checkout main
branch hotfix/critical
commit id: "Critical fix"
checkout main
merge hotfix/critical
checkout production
merge main id: "Hotfix to prod"
Concepto GitLab Flow
GitLab Flow es un híbrido entre GitHub Flow (simplicidad) y GitFlow (control releases). Introduce environment branches (staging, production) para mapear Git branches a deployment environments.
Diferencias clave:
- GitHub Flow: main = producción inmediata (CD puro)
- GitFlow: develop + release branches (complejo)
- GitLab Flow: main + environment branches (balance)
Variantes GitLab Flow
1. Production branch (downstream)
# Desarrollo en main
git checkout main
git checkout -b feature/new-dashboard
git commit -m "Add analytics dashboard"
git push origin feature/new-dashboard
# Merge a main (como GitHub Flow)
git checkout main
git merge feature/new-dashboard
# Deploy a staging (automático CI/CD)
git checkout staging
git merge main
git push origin staging
# CI/CD → Deploy to staging environment
# Si staging OK → Deploy a production
git checkout production
git merge staging
git push origin production
# CI/CD → Deploy to production environment
Estructura:
main (latest code, may be unstable)
↓ merge
staging (testing environment)
↓ merge (after QA approval)
production (production environment)
2. Release branches (upstream, like GitFlow lite)
# Para software con versiones (mobile apps, libraries)
git checkout main
git checkout -b release/2.3
# Deploy release branch a stores/registries
# Hotfixes en release branch
git checkout -b hotfix/2.3.1 release/2.3
git commit -m "Fix crash on Android 12"
git checkout release/2.3
git merge hotfix/2.3.1
git tag v2.3.1
# Merge hotfix back a main
git checkout main
git merge hotfix/2.3.1
3. Environment branches + Release branches (híbrido)
# Para equipos grandes con múltiples environments + versiones
main
↓
staging (test environment)
↓
pre-production (UAT environment)
↓
production (live environment)
# + Release branches para versiones legacy
release/2.0 (support 2.0.x)
release/3.0 (support 3.0.x)
Workflow GitLab Flow detallado
Feature development:
# 1. Crear feature branch desde main
git checkout main
git pull origin main
git checkout -b feature/user-notifications
# 2. Desarrollo + commits
git add .
git commit -m "Add push notification service"
git push origin feature/user-notifications
# 3. Merge request (GitLab) o pull request
# Reviewers aprueban, CI/CD tests pasan
# 4. Merge a main
git checkout main
git merge --no-ff feature/user-notifications
git push origin main
Deployment pipeline (environment branches):
# .gitlab-ci.yml
stages:
- build
- test
- deploy-staging
- deploy-production
deploy_staging:
stage: deploy-staging
script:
- echo "Deploying to staging..."
- ./deploy.sh staging
only:
- staging # Trigger cuando staging branch actualiza
environment:
name: staging
url: https://staging.example.com
deploy_production:
stage: deploy-production
script:
- echo "Deploying to production..."
- ./deploy.sh production
only:
- production # Trigger cuando production branch actualiza
environment:
name: production
url: https://example.com
when: manual # Require manual approval
Promotion workflow:
# Código pasa: main → staging → production
# Step 1: Merge feature a main
git checkout main
git merge feature/payment-gateway
# Step 2: Promote main to staging (automático o manual)
git checkout staging
git merge main
git push origin staging
# GitLab CI/CD → Deploy to staging.example.com
# Step 3: QA testing en staging (manual)
# Testers validan en staging environment
# Step 4: Promote staging a production (manual approval)
git checkout production
git merge staging # O merge main directamente
git push origin production
# GitLab CI/CD → Manual approval → Deploy to example.com
Hotfix workflow GitLab Flow
# Bug crítico en production
# Opción A: Fix en main, fast-forward a production
git checkout main
git checkout -b hotfix/security-patch
git commit -m "Fix: SQL injection vulnerability"
git checkout main
git merge hotfix/security-patch
# Skip staging, merge directo a production (emergency)
git checkout production
git merge main
git push origin production
# Opción B: Cherry-pick a production (si main divergió mucho)
git checkout production
git cherry-pick <commit-hash-from-main>
git push origin production
# Sync staging después
git checkout staging
git merge main
Ventajas GitLab Flow
✅ Environment branches = Visual deployment state: Cada branch refleja estado de un environment real
✅ Flexible: Funciona con CD continuo (production branch) o releases planificadas (release branches)
✅ Simple que GitFlow: Sin develop branch, menos complejidad
✅ Control deployment: Staging → Production promotion manual/automática
✅ GitLab CI/CD integration: Environment branches = GitLab environments con URLs, logs, rollbacks
Desventajas GitLab Flow
❌ Merge overhead: Main → staging → production = 2 merges por deploy
❌ Divergence risk: Si production tiene hotfixes no mergeados a main = conflicts
❌ Not pure CD: Production branch añade friction vs GitHub Flow (deploy from main)
❌ Environment drift: Staging puede divergir de production (config differences)
Cuándo usar GitLab Flow
- ✅ Equipos medianos (5-30 devs)
- ✅ Múltiples environments (dev/staging/pre-prod/prod)
- ✅ Manual QA en staging before production
- ✅ Deploy frequency variable (no necesariamente CD extremo)
- ✅ Usando GitLab CI/CD (integration nativa)
- ❌ NO si haces CD puro desde main (usa GitHub Flow)
OneFlow
Arquitectura OneFlow
gitGraph
commit id: "Init"
commit id: "v1.0.0" tag: "v1.0.0"
branch feature/api
checkout feature/api
commit id: "API work"
checkout main
merge feature/api
branch release/1.1
checkout release/1.1
commit id: "RC 1.1.0"
commit id: "Bug fix"
checkout main
merge release/1.1 tag: "v1.1.0"
branch feature/ui
checkout feature/ui
commit id: "UI work"
checkout main
merge feature/ui
branch hotfix/1.1.1
checkout hotfix/1.1.1
commit id: "Critical fix"
checkout main
merge hotfix/1.1.1 tag: "v1.1.1"
Concepto OneFlow
OneFlow es una simplificación de GitFlow creada por Adam Ruka. Elimina el develop branch (principal diferencia con GitFlow), manteniendo solo main como branch principal.
GitFlow vs OneFlow:
| Aspecto | GitFlow | OneFlow |
|---|---|---|
| Main branch | main (producción) | main (desarrollo + producción) |
| Develop branch | develop (desarrollo) | ❌ Eliminado |
| Feature branches | Desde develop | Desde main |
| Release branches | Desde develop → merge a main + develop | Desde main → merge back a main |
| Hotfix branches | Desde main → merge a main + develop | Desde main/release → merge a main |
| Complejidad | 🔴 Alta | 🟡 Media |
Workflow OneFlow
Feature development:
# Crear feature branch desde main (igual que GitHub Flow)
git checkout main
git pull origin main
git checkout -b feature/shopping-cart
# Desarrollo
git commit -m "Add cart service"
git commit -m "Add cart UI components"
git push origin feature/shopping-cart
# Pull request a main
gh pr create --base main --head feature/shopping-cart
# Merge a main (squash)
gh pr merge --squash --delete-branch
Release process (diferencia clave vs GitHub Flow):
# Cuando listo para release → crear release branch
git checkout main
git checkout -b release/2.0.0
# Bump version, changelog, release notes
git commit -m "chore: Bump version to 2.0.0"
# Bug fixes en release branch (como GitFlow)
git commit -m "fix: Validation error in checkout"
git commit -m "fix: Typo in confirmation email"
# Tag release
git tag -a v2.0.0 -m "Release 2.0.0"
git push origin release/2.0.0 --tags
# Deploy release branch a producción
# Merge release branch BACK to main (diferencia con GitFlow)
git checkout main
git merge --no-ff release/2.0.0
git push origin main
# Release branch puede mantenerse (para hotfixes) o eliminarse
Hotfix workflow:
# Opción A: Hotfix desde release branch (si existe)
git checkout release/2.0.0
git checkout -b hotfix/2.0.1
git commit -m "fix: Critical security patch"
git checkout release/2.0.0
git merge hotfix/2.0.1
git tag -a v2.0.1 -m "Hotfix 2.0.1"
git push origin release/2.0.0 --tags
# Merge hotfix a main
git checkout main
git merge hotfix/2.0.1
git push origin main
# Opción B: Hotfix desde main (si no hay release branch)
git checkout main
git checkout -b hotfix/critical-fix
git commit -m "fix: Emergency patch"
git checkout main
git merge hotfix/critical-fix
git tag -a v2.0.1 -m "Hotfix 2.0.1"
Variantes OneFlow
1. Short-lived release branches (recomendado):
# Release branch solo durante RC testing (1-2 semanas)
git checkout -b release/3.0.0
# Testing + bug fixes
git tag v3.0.0
git checkout main
git merge release/3.0.0
git branch -d release/3.0.0 # Eliminar después de release
2. Long-lived release branches (múltiples versiones):
# Mantener release branches para support largo plazo
release/2.0 # Support 2.0.x (6 meses)
release/3.0 # Support 3.0.x (current)
main # Development 4.0
Ventajas OneFlow
✅ Más simple que GitFlow: Sin develop branch = menos complejidad
✅ Main siempre buildable: Como Trunk-Based, main es source of truth
✅ Flexible release timing: Release branches cuando necesites, no obligatorios
✅ Hotfix process claro: Desde release o main, merge back to main
✅ Historia limpia: Merge commits claros para releases
Desventajas OneFlow
❌ No tan simple como GitHub Flow: Release branches añaden complejidad
❌ Merge back confusion: Devs pueden olvidar merge release → main
❌ No apto para CD extremo: Release branches conflicts con continuous deployment
Cuándo usar OneFlow
- ✅ Equipos medianos (10-50 devs)
- ✅ Releases planificadas pero no extremadamente rigurosas
- ✅ Quieres simplicidad de GitHub Flow + release branches de GitFlow
- ✅ SaaS con versioning (v2.x, v3.x) pero sin develop branch
- ❌ NO si haces CD múltiples veces/día (usa GitHub Flow o Trunk-Based)
Feature Branch Workflow (básico)
Arquitectura Feature Branch
gitGraph
commit id: "Init"
commit id: "v1.0.0" tag: "v1.0.0"
branch feature/payment
checkout feature/payment
commit id: "Stripe integration"
commit id: "Payment UI"
checkout main
branch feature/notifications
checkout feature/notifications
commit id: "Email service"
checkout main
merge feature/payment
commit id: "v1.1.0" tag: "v1.1.0"
checkout feature/notifications
commit id: "Push notifications"
checkout main
merge feature/notifications
commit id: "v1.2.0" tag: "v1.2.0"
Workflow básico
# 1. Crear feature branch
git checkout main
git pull origin main
git checkout -b feature/add-search
# 2. Desarrollo
git add src/search/
git commit -m "Add full-text search with Elasticsearch"
git push origin feature/add-search
# 3. Pull request
gh pr create --base main --head feature/add-search
# 4. Code review + CI
# 5. Merge (squash/merge/rebase según preferencia team)
gh pr merge --squash --delete-branch
# 6. Pull main actualizado
git checkout main
git pull origin main
Ventajas Feature Branch
✅ Simplicidad máxima: Solo main + feature branches (como GitHub Flow sin deploy pre-merge)
✅ Flexible: Funciona con CI/CD o sin él
✅ Code review natural: Pull requests obligatorios
Desventajas Feature Branch
❌ Long-lived branches risk: Sin disciplina, branches viven semanas/meses
❌ No hotfix process: Hotfixes = feature branches (no distinción)
❌ Merge conflicts: Si branches viven >1 semana
Cuándo usar Feature Branch
- ✅ Equipos muy pequeños (<5 devs)
- ✅ Sin CI/CD maduro (manual QA)
- ✅ Proyectos open-source (contributors externos)
- ✅ Prototipado/MVPs (no producción crítica)
Elección de estrategia
Flowchart decisión
¿Tamaño equipo?
├─ <5 devs → Feature Branch Workflow
├─ 5-20 devs →
│ ├─ CD diario → GitHub Flow
│ ├─ Múltiples environments → GitLab Flow
│ └─ Sprint releases → Release Flow (si >20 devs)
├─ 10-50 devs →
│ ├─ Releases con versioning → OneFlow
│ └─ Environments staging/prod → GitLab Flow
└─ >50 devs →
├─ CD extremo (Google/FB) → Trunk-Based
├─ Sprint releases (Microsoft) → Release Flow
└─ Releases planificadas largas → GitFlow
¿Frecuencia deployment?
├─ Múltiples/día → Trunk-Based o GitHub Flow
├─ Diario con staging → GitLab Flow
├─ Sprint-based (2-3 semanas) → Release Flow o OneFlow
└─ Mensual/trimestral → GitFlow
¿CI/CD maturity?
├─ Alto (tests <5 min, deploy <10 min) → Trunk-Based
├─ Medio (tests <20 min) → GitHub Flow / Release Flow / GitLab Flow
├─ Medio-bajo (manual QA staging) → GitLab Flow / OneFlow
└─ Bajo (manual QA) → GitFlow / Feature Branch
¿Versiones en producción?
├─ Single version (SaaS) → GitHub Flow / Trunk-Based
├─ Environments (staging/prod) → GitLab Flow
├─ 2-3 versions (rings) → Release Flow
├─ Versioning semántico (v2.x, v3.x) → OneFlow
└─ Múltiples versiones legacy → GitFlow
¿Herramienta principal?
├─ GitLab → GitLab Flow (environment integration)
├─ GitHub → GitHub Flow / Release Flow
├─ Azure DevOps → Release Flow
└─ Tool-agnostic → Trunk-Based / OneFlow
Migración entre estrategias
GitFlow → OneFlow:
# 1. Merge develop a main (one-time)
git checkout main
git merge develop --ff-only
git push origin main
# 2. Eliminar develop branch
git push origin --delete develop
# 3. Feature branches desde main (no desde develop)
# 4. Release branches merge back a main
GitFlow → GitHub Flow:
# 1. Eliminar develop branch (como OneFlow)
git checkout main
git merge develop --ff-only
git push origin main
git push origin --delete develop
# 2. Eliminar release branches long-lived
# 3. Habilitar CD pipeline (deploy on merge to main)
# 4. Feature flags para features incompletas
GitHub Flow → GitLab Flow:
# 1. Crear staging branch desde main
git checkout -b staging main
git push origin staging
# 2. Crear production branch desde staging
git checkout -b production staging
git push origin production
# 3. Workflow: main → staging → production
# 4. Configurar GitLab CI/CD environments
GitLab Flow → GitHub Flow:
# 1. Eliminar environment branches (staging/production)
git push origin --delete staging production
# 2. Deploy directamente desde main
# 3. CI/CD deploy on merge to main
Feature Branch → Trunk-Based:
# 1. Reducir lifetime branches (<24h)
# 2. Implementar feature flags
# 3. Commits más frecuentes (daily)
# 4. Fast CI/CD (<5 min)
GitHub Flow → Release Flow:
# 1. Mantener main como trunk
# 2. Crear release branches al fin de sprint
git checkout -b releases/M1 main
# 3. Hotfixes via cherry-pick
OneFlow → Release Flow:
# 1. Release branches long-lived (no merge back)
# 2. Cherry-pick hotfixes en lugar de merge
# 3. Sprint cadence (crear release cada N semanas)
Mejores prácticas (universales)
1. Keep branches short-lived
# ❌ BAD: Branch vive 6 semanas
git log --oneline feature/new-api
# 2024-09-01: Start new API
# 2024-10-15: Finish new API (89 commits, 5000 LoC changed)
# ✅ GOOD: Branch vive 2 días
git log --oneline feature/api-user-endpoint
# 2024-10-13: Add user endpoint (3 commits, 150 LoC)
Táctica: Break down large features
# Gran feature: Rewrite API (6 semanas)
# Dividir en:
feature/api-models # 2 días
feature/api-user-endpoint # 2 días
feature/api-auth-endpoint # 3 días
feature/api-data-endpoint # 2 días
# Total: 9 días distribuidos en 6 semanas (parallel + smaller PRs)
2. Commit frequently, push daily
# ❌ BAD: 1 commit gigante al final
git commit -m "Implement entire checkout flow" # 2000 LoC
# ✅ GOOD: Commits incrementales
git commit -m "Add checkout page component" # 150 LoC
git commit -m "Integrate payment gateway" # 200 LoC
git commit -m "Add order confirmation email" # 100 LoC
git commit -m "Add checkout flow tests" # 300 LoC
3. Sync con main frecuentemente
# Daily: actualizar feature branch con main
git checkout feature/my-feature
git fetch origin
git rebase origin/main # o merge si prefieres
git push --force-with-lease origin feature/my-feature
4. Squash merges para historia limpia
# ❌ Historia main sucia
* feat: Add login
* WIP
* Fix typo
* Linter errors
* Final fixes
* Merge feature/login
# ✅ Historia main limpia (squash)
* feat: Add login with OAuth support (#234)
5. Naming conventions consistentes
# Tipos de branches
feature/ → Nuevas features
bugfix/ → Bug fixes
hotfix/ → Emergency production fixes
release/ → Release branches
docs/ → Documentation updates
# Con ticket ID
feature/JIRA-1234-user-authentication
bugfix/GH-456-fix-memory-leak
# Con username (large teams)
users/alice/feature-oauth
users/bob/bugfix-validation
6. Branch protection rules
# GitHub branch protection (main)
required_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
required_status_checks:
strict: true # Require up-to-date with main
contexts:
- ci/tests
- ci/build
- security/scan
enforce_admins: false # Admins pueden bypass para hotfixes
allow_force_pushes: false
allow_deletions: false
7. Automated CI/CD gates
# Checks obligatorios antes de merge
- Lint pass
- Unit tests pass (coverage >80%)
- Integration tests pass
- Build success
- Security scan (no critical vulnerabilities)
- Performance regression (<10% degradation)
Casos de uso reales
Startup (5 devs, MVP)
Estrategia: Feature Branch Workflow
# Simple: main + feature branches
# Manual QA, deploy semanal
# Sin CI/CD inicial
git checkout -b feature/user-signup
# Desarrollo 3 días
gh pr create --base main
# Manual review + test en staging
gh pr merge --squash
# Deploy manual viernes
Scale-up (20 devs, product-market fit)
Estrategia: GitHub Flow
# CD pipeline implementado
# Deploy múltiple/día
# Feature flags para features grandes
git checkout -b feature/premium-tier
# Feature flag: premium_tier_enabled = false
git push origin feature/premium-tier
# CI/CD deploy a staging automático
# Habilitar flag para testing interno
featureFlags.enable('premium_tier_enabled', { users: ['internal'] })
# Merge → deploy a prod (flag disabled para users)
gh pr merge --squash
# Gradual rollout
featureFlags.enable('premium_tier_enabled', { rollout: 10 }) # 10%
featureFlags.enable('premium_tier_enabled', { rollout: 100 }) # 100%
Enterprise (500 devs, múltiples productos)
Estrategia: Release Flow
# Sprint 3-semanas
# 200+ PRs/día merging a main
# Release branch por sprint
# Developer workflow
git checkout -b users/alice/JIRA-5678-api-v3
# 2 días desarrollo
az repos pr create --target-branch main
# Sprint end (cada 3 semanas)
git checkout -b releases/2024.11
# Deploy ring-based (1% → 10% → 50% → 100%)
# Hotfix mid-sprint
git checkout -b users/bob/hotfix-auth
# Fix en main
az repos pr complete
# Cherry-pick to releases/2024.11
Google-scale (1000+ devs, monorepo)
Estrategia: Trunk-Based Development
# Commits directos a trunk (o branches <24h)
# 40,000+ commits/día
# Tests ultra-rápidos (<5 min)
# Presubmit tests (antes de commit)
bazel test //services/search:unit_tests # 30 sec
# Commit
git commit -m "Optimize search ranking algorithm"
git push origin main
# Postsubmit tests (async, post-commit)
bazel test //... # Full test suite, 30 min
# Auto-rollback si postsubmit falla
Herramientas
Git aliases útiles
# ~/.gitconfig
[alias]
# Sync con main rápido
sync = !git fetch origin && git rebase origin/main
# Historia limpia
lg = log --graph --oneline --all --decorate
# Squash últimos N commits
squash = "!f() { git reset --soft HEAD~$1 && git commit; }; f"
# Limpiar branches mergeadas
clean-merged = "!git branch --merged | grep -v '\\*\\|main\\|develop' | xargs -n 1 git branch -d"
Azure DevOps CLI
# Crear PR desde CLI
az repos pr create \
--title "feat: Add Redis caching layer" \
--description "Implements Redis cache for API responses. Reduces latency 70%." \
--source-branch feature/redis-cache \
--target-branch main \
--reviewers alice@contoso.com bob@contoso.com
# Auto-complete PR con policies
az repos pr update \
--id 1234 \
--auto-complete true \
--squash true \
--delete-source-branch true
GitHub CLI
# Crear PR con labels/reviewers
gh pr create \
--title "feat: Add Stripe payment integration" \
--body "Closes #456" \
--base main \
--head feature/stripe \
--reviewer alice,bob \
--label enhancement,high-priority
# Merge con squash
gh pr merge 123 --squash --delete-branch --admin
Resumen comparativo
| Métrica | GitFlow | GitHub Flow | GitLab Flow | Trunk-Based | Release Flow | OneFlow |
|---|---|---|---|---|---|---|
| Complejidad aprendizaje | 🔴 Alta | 🟢 Baja | 🟡 Media | 🟡 Media | 🟡 Media | 🟡 Media |
| Merge conflicts | 🔴 Frecuentes | 🟡 Ocasionales | 🟡 Ocasionales | 🟢 Raros | 🟢 Raros | 🟡 Ocasionales |
| Deploy velocity | 🔴 Lento (semanal) | 🟢 Rápido (diario) | � Variable | �🟢 Ultra-rápido | 🟡 Sprint-based | 🟡 Sprint/semanal |
| CI/CD requirement | 🟡 Medio | 🟢 Alto | 🟢 Alto | 🔴 Muy alto | 🟢 Alto | 🟡 Medio |
| Hotfix support | 🟢 Excelente | 🟡 Bueno | 🟢 Excelente | 🟡 Bueno | 🟢 Excelente | 🟢 Excelente |
| Multi-version support | 🟢 Excelente | 🔴 Pobre | � Bueno | 🔴 Pobre | 🟡 Bueno | 🟢 Bueno |
| Environment control | 🔴 Pobre | 🔴 Pobre | 🟢 Excelente | �🔴 Pobre | 🟡 Bueno | 🔴 Pobre |
| Team size óptimo | >10 devs | 3-20 devs | 5-30 devs | >50 devs | >50 devs | 10-50 devs |
| Usado por | Legacy enterprise | Startups/SaaS | GitLab users | Google/Facebook | Microsoft Azure | Mid-size teams |