ruta backend / módulo 7

M7 — Git avanzado & semántica HTTP

Dos fundamentos que el mercado da por sentados y hunden entrevistas cuando fallan (ambos aparecieron como gap en pruebas técnicas reales).

Outcome del módulo: resolver un conflicto de merge sin romper nada, reescribir historia local con criterio, y diseñar una API que respete la semántica HTTP (métodos, status, idempotencia).


Concepto 1 — Git avanzado (rebase, cherry-pick, conflictos)

Idea núcleo: más allá de add/commit/push, un senior maneja historia: integra ramas limpio, mueve commits puntuales y resuelve conflictos con criterio.

Entender (capa 1)

Texto:

Visual:

flowchart TD
    Q{¿qué necesito?} -->|integrar rama compartida| MERGE[merge · preserva historia]
    Q -->|limpiar historia local antes de PR| REBASE[rebase · lineal, solo local]
    Q -->|un commit puntual a otra rama| CP[cherry-pick]
    Q -->|encontrar qué commit rompió| BISECT[git bisect]

Video: Git Merge vs Rebase Explained in 100 Seconds — Thetips4you

Ejemplo:

# resolver conflicto durante un rebase
git rebase main
# ... Git marca conflicto en archivo.py ...
# editás, elegís la versión correcta, luego:
git add archivo.py
git rebase --continue          # (o git rebase --abort para cancelar todo)

# llevar solo un hotfix a otra rama
git cherry-pick <hash-del-commit>

# encontrar el commit que introdujo un bug
git bisect start; git bisect bad; git bisect good <hash-viejo>

Fijar (capa 2)

Nota atómica:

Feynman: “Merge es unir dos ríos y dejar ver dónde se juntaron. Rebase es reescribir tu diario para que parezca que siempre fuiste por el mismo camino — genial para tu diario privado, catástrofe si reescribís el diario compartido del equipo.”

Aplicar (capa 3)

Creá dos ramas que toquen la misma línea, provocá un conflicto y resolvelo. Después hacé un rebase -i para hacer squash de 3 commits en 1, y un cherry-pick de un commit a otra rama.

Límites


Concepto 2 — Semántica HTTP

Idea núcleo: cada método y status code tiene un significado contractual. Respetarlo hace tu API predecible, cacheable y correcta; ignorarlo la vuelve un campo minado.

Entender (capa 1)

Texto:

Visual:

flowchart LR
    M[método] --> G[GET · seguro · cacheable]
    M --> PO[POST · crea · NO idempotente]
    M --> PU[PUT · reemplaza · idempotente]
    M --> DE[DELETE · idempotente]

Video: HTTP Methods Explained | GET, POST, PUT, and Idempotency in Simple Terms — Leela Web Dev

Ejemplo (mal → bien):

# ❌ todo por POST y siempre 200: rompe caching, retries y clientes
@app.post("/get-user")           # debería ser GET
def get_user(): return {"ok": True}   # 200 hasta cuando falla

# ✅ semántica correcta
@app.get("/users/{id}")          # GET para leer
def get_user(id):
    u = db.get(id)
    if u is None:
        raise HTTPException(404)  # no existe → 404, no 200
    return u                      # 200 con el recurso

@app.post("/users", status_code=201)  # crear → 201
def create_user(data): ...

Fijar (capa 2)

Nota atómica:

Feynman: “PUT es el interruptor de la luz: lo aprietes una o cinco veces, queda en el estado que pediste. POST es agregar un plato a la mesa: cada vez que lo mandás, aparece otro plato.”

Aplicar (capa 3)

Tomá una API que usa POST para todo y devuelve 200 siempre; reescribila con métodos y status correctos (GET/POST/PUT/DELETE, 201/404/422). Verificá con curl -i que los status son correctos.

Límites


Checklist de dominio M7

Marcás cuando podés explicar (Feynman) + aplicar:

Salida verificable del módulo: resolver un conflicto de rebase real + hacer squash de una rama antes de un PR; y una API con métodos/status/idempotencia correctos verificados con curl -i.