DevOps desde Cero: Control de Versiones para Equipos

2026-04-27 | Gabriel Garrido | 6 min de lectura
Share:

Apoya este blog

Si te resulta util este contenido, considera apoyar el blog.

Introduccion

Bienvenido al articulo 3 de la serie DevOps desde Cero. Ahora es momento de hablar sobre una de las herramientas mas criticas en cualquier equipo de ingenieria: el control de versiones para equipos.


Si estas trabajando solo, podes salir adelante commiteando directamente a main. Pero en el momento en que una segunda persona toca el mismo codebase, necesitas estructura, convenciones y barreras de seguridad. En este articulo vamos a cubrir estrategias de branching, pull requests, commits convencionales, branches protegidos y estrategias de merge.


Por que importa el control de versiones en DevOps

El control de versiones es la base para todo lo que vas a construir en DevOps:


  • Colaboracion Multiples personas pueden trabajar en el mismo codebase simultaneamente sin sobreescribir los cambios del otro
  • Auditabilidad Cada cambio queda registrado con timestamp, autor y mensaje. Podes rastrear exactamente que cambio y quien lo cambio
  • Rollback Hiciste un deploy malo? Volve a un estado anterior conocido en segundos
  • Automatizacion Los pipelines de CI/CD se disparan basandose en eventos de Git. Sin control de versiones, no podes automatizar builds, tests ni deployments
  • Code review Los pull requests crean un proceso estructurado para revisar cambios antes de que lleguen a produccion

Estrategias de Branching

Una estrategia de branching define como tu equipo usa branches para desarrollar, testear y liberar software. Veamos las tres mas comunes.


Trunk-Based Development

Todos commitean a un solo branch (main). Los feature branches son de vida corta, duran no mas de uno o dos dias.


main ─────●─────●─────●─────●─────●─────●─────
            \       /   \     /
feature-a    ●───●     feature-b

  • Branches de vida corta Las features se dividen en pedazos chicos que se mergean en un dia o dos
  • Feature flags Las features incompletas se esconden detras de flags para que se puedan mergear de forma segura
  • Integracion continua Todos integran frecuentemente, reduciendo conflictos de merge

Esta es la estrategia que recomiendo para la mayoria de los equipos. Empresas como Google y Netflix la usan a escala.


GitFlow

Usa multiples branches de vida larga: main, develop, feature/*, release/* y hotfix/*. Disenado para equipos con releases programados.


main     ─────●───────────────────●──────────────
               \                 /
develop   ──●───●───●───●───●───●───●───●────────
              \   /       \       /
feature-a      ●──●        release/1.0

Bueno para software versionado (librerias, apps moviles), pero agrega complejidad innecesaria para aplicaciones web que se deployean continuamente.


GitHub Flow

Workflow simplificado: main y feature branches de vida corta. Abris un PR, conseguis un review, mergeas. Eso es todo.


  • Simple Solo dos tipos de branches: main y feature branches
  • Orientado a PRs Cada cambio pasa por un pull request
  • Deploy desde main El branch main siempre esta deployable

Para la mayoria de los equipos que construyen aplicaciones web, usa trunk-based development o GitHub Flow. Usa GitFlow solo si genuinamente necesitas ciclos de release estructurados.


Pull Requests: El Corazon de la Colaboracion

Un pull request es mas que una solicitud de merge. Es una conversacion sobre los cambios que estas proponiendo. Los buenos PRs son la practica mas importante para mantener la calidad del codigo.


Como se ve un buen PR

## Que
Descripcion breve de que hace este PR.

## Por que
Por que se necesita este cambio? Link al issue o ticket.

## Como
Resumen de alto nivel del enfoque.

## Testing
Como se testeo? Incluye comandos de test relevantes o screenshots.

## Checklist
- [ ] Tests pasan localmente
- [ ] Documentacion actualizada si es necesario
- [ ] Sin cambios que rompan (o ruta de migracion documentada)

Mejores practicas para reviews

  • Se constructivo Sugeri mejoras, ofrece alternativas cuando no estes de acuerdo
  • Enfocate en lo importante Arquitectura y correctitud por sobre preferencias de estilo. Deja que el linter se encargue del formateo
  • Hace preguntas “Podrias explicar por que se eligio este enfoque?” es mejor que “Esto esta mal”
  • Revisa rapido Los PRs bloqueados matan el momentum. Revisa en horas, no en dias
  • Mantene los PRs chicos Apunta a menos de 400 lineas. Los PRs grandes reciben aprobaciones sin revision real

Commits Convencionales

Los commits convencionales son una especificacion para mensajes de commit estructurados que habilitan changelogs automaticos y bumps de version.


El Formato

<tipo>(<scope>): <descripcion>

[cuerpo opcional]
[footer(s) opcionales]

Tipos comunes: feat, fix, docs, style, refactor, test, chore, ci, perf.


Ejemplos

feat(auth): add OAuth2 login with GitHub
fix(api): handle null response from payment gateway
docs(readme): update installation instructions for v2
chore(deps): bump phoenix_live_view from 1.0.0 to 1.1.0
refactor(database): extract connection pooling into separate module
ci(github-actions): add Elixir formatter check to PR workflow
feat(notifications)!: redesign notification system

BREAKING CHANGE: notification payloads now use snake_case keys

  • Changelogs automaticos Herramientas como release-please generan changelogs desde el historial de commits
  • Versionado semantico El tipo del commit determina patch (fix), minor (feat) o major (breaking change)
  • Historial legible git log --oneline se convierte en una historia clara de que paso

Branches Protegidos

Los branches protegidos previenen acciones peligrosas en branches importantes como main. Asi se configuran en GitHub:


  1. Anda a tu repositorio, despues Settings > Branches
  2. Hace click en Add branch protection rule, configura el patron a main
  3. Configura las reglas:

[x] Require a pull request before merging
    [x] Require approvals: 1
    [x] Dismiss stale approvals when new commits are pushed

[x] Require status checks to pass before merging
    [x] Require branches to be up to date before merging

[x] Do not allow force pushes
[x] Do not allow deletions
[x] Do not allow bypassing the above settings

Tambien podes hacerlo con el GitHub CLI:

gh api repos/{owner}/{repo}/branches/main/protection \
  --method PUT \
  --input - <<'EOF'
{
  "required_status_checks": {
    "strict": true,
    "contexts": ["ci/tests", "ci/lint"]
  },
  "enforce_admins": true,
  "required_pull_request_reviews": {
    "dismiss_stale_reviews": true,
    "required_approving_review_count": 1
  },
  "restrictions": null,
  "allow_force_pushes": false,
  "allow_deletions": false
}
EOF

Archivo CODEOWNERS

Define quien revisa cambios en partes especificas del codebase:

# .github/CODEOWNERS
* @tu-equipo/backend
/assets/ @tu-equipo/frontend
/terraform/ @tu-equipo/platform
/.github/workflows/ @tu-equipo/platform @tu-equipo/leads

Estrategias de Merge

Cuando mergeas un PR en GitHub, tenes tres opciones:


Merge Commit preserva todos los commits individuales mas un merge commit. Historial completo, pero puede ponerse desordenado.

# * abc1234 Merge pull request #42
# |\
# | * def5678 fix: handle edge case
# | * ghi9012 feat: add JWT validation
# |/
# * mno7890 Commit anterior

Squash and Merge combina todos los commits en uno solo en main. Historial limpio y lineal.

# * abc1234 feat(auth): add JWT authentication (#42)
# * mno7890 Commit anterior

Rebase and Merge reproduce los commits individuales encima de main. Historial lineal con todo el detalle.

# * abc1234 fix: handle edge case
# * def5678 feat: add JWT validation
# * ghi9012 feat: add login endpoint
# * mno7890 Commit anterior

Para la mayoria de los equipos, squash and merge es el punto justo. Mantiene main limpio y fomenta PRs chicos y enfocados.


Tips Practicos

Nombres de branches significativos con prefijos consistentes:

feature/add-oauth-login
fix/null-pointer-in-payment
chore/upgrade-elixir-to-1.17
docs/update-api-reference

Commits atomicos donde cada commit representa un cambio logico:

git add lib/auth/session.ex
git commit -m "fix(auth): prevent session fixation on password reset"

git add test/auth/session_test.exs
git commit -m "test(auth): add regression test for session fixation"

Rebasea antes de mergear para mantener tu branch actualizado:

git fetch origin
git rebase origin/main
# Usa --force-with-lease en vez de --force (mas seguro)
git push --force-with-lease origin feature/add-auth

Limpia los branches mergeados para evitar desorden:

git fetch --prune
git branch --merged main | grep -v "main" | xargs git branch -d

Notas finales

El control de versiones es la columna vertebral de como los equipos colaboran y como el codigo llega a produccion de forma segura. Tener tu workflow de Git bien configurado desde el principio te ahorra cantidades enormes de dolor a futuro.


Los puntos clave: usa trunk-based development o GitHub Flow, mantene los PRs chicos, adopta commits convencionales, protege tu branch main y usa squash merges. Empeza simple, agrega complejidad solo cuando la necesites.


En el proximo articulo, vamos a meternos de lleno en pipelines de CI/CD. Estemos atentos!


Errata

Si encontras algun error o tenes alguna sugerencia, mandame un mensaje asi se corrige.

Tambien podes ver el codigo fuente y ejemplos en el repositorio aca.


$ Comentarios

Online: 0

Por favor inicie sesión para poder escribir comentarios.

2026-04-27 | Gabriel Garrido