Cómo leer esta guía
Esta guía cubre el flujo completo de Pull Requests en GitHub: por qué existen, cómo abrirlos bien, cómo dar y recibir review, y qué hacer cuando algo se rompe. Está pensada para auto-servicio — no necesitás leerla entera de una sentada.
Está dividida en tres partes:
- I · El porqué — qué es un PR, para qué sirve, por qué importa. Si nunca abriste uno o querés entender el contexto, empezá acá.
- II · El flujo — el camino de un PR de principio a fin: desde crear la branch hasta apretar el botón de merge. Léelo en orden la primera vez; volvé a una sección puntual cuando la necesites.
- III · Cuando algo se rompe — troubleshooting. No leas en orden: cuando te aparezca un error o un mensaje raro, buscá el síntoma y saltá ahí.
Las secciones de troubleshooting (Parte III) arrancan con el síntoma que vas a ver (mensaje de error, banner de GitHub) para que las identifiques rápido. Las de las Partes I y II son más narrativas. Todas terminan con un autocheck para confirmar que se entendió.
Para la Parte I, ninguno. Para la Parte II, conocer commit, push y branch ayuda. Para la Parte III, haber abierto al menos un PR antes te va a dar más contexto. Si te falta algo, los enlaces al final apuntan a Pro Git (gratuito).
Tip de lectura: tocá, enfocá o pasá el mouse sobre las líneas marcadas en los bloques de código para ver explicaciones contextuales.
I · El porqué
1. ¿Qué es un Pull Request y por qué existe?
Un Pull Request (PR) es una propuesta: "hice estos cambios en una branch aparte, ¿podemos discutirlos y meterlos al código principal?". No es un mecanismo de git — es una capa de colaboración que GitHub (y GitLab, Bitbucket, etc.) construyeron encima de git.
Para entender por qué existen los PRs, ayuda imaginar el mundo sin ellos. Antes de GitHub, equipos enteros trabajaban directo sobre master: alguien rompía el build a las 6pm de un viernes, y el lunes el equipo entero descubría que no compilaba. La revisión —si existía— era un email con un parche adjunto. Las decisiones arquitectónicas se discutían en pasillos y se perdían.
El PR resuelve eso con tres cosas chicas pero potentes: (a) los cambios viven en una branch aislada hasta que alguien los apruebe, (b) hay una URL única donde discutir línea por línea, y (c) queda un registro permanente de qué se cambió, quién lo aprobó, y por qué.
Hoy los PRs son el contrato base de cómo trabajan equipos de software. Si alguna vez vas a contribuir a un proyecto open source, postularte a un trabajo técnico, o simplemente colaborar con alguien más que vos en un repo — vas a hacerlo via PR.
- Un PR no es lo mismo que un
git push: el push solo manda commits al remote; el PR es la propuesta de mergearlos. - En GitLab se llaman Merge Requests. La idea y mecánica son idénticas; el nombre es más preciso.
- Una branch puede vivir sin PR (por ejemplo para experimentos personales). Un PR siempre vive sobre una branch.
¿Cuál es la diferencia clave entre un git push y abrir un PR?
2. El propósito real (cuatro trabajos en uno)
Es fácil pensar el PR como "el paso antes del merge". Pero un PR está haciendo cuatro trabajos al mismo tiempo, y entender cada uno te ayuda a no saltarte ninguno.
1. Revisar código. Otro par de ojos detecta bugs, simplificaciones, problemas de seguridad. La regla empírica: los reviewers encuentran ~60% de los bugs que CI no detecta. No reemplazan los tests; los complementan.
2. Dejar contexto histórico. Dentro de dos años, alguien va a hacer git blame sobre una línea rara y va a llegar al commit. De ahí al PR. Y ahí va a leer la descripción, las preguntas que hicieron los reviewers, y por qué se eligió esa solución y no otra. El PR es la documentación que sobrevive cuando los docs no.
3. Gate de calidad (CI). Tests, lint, type-check, build, deploy a preview. Si algo de eso falla, el merge no se habilita. El PR es el lugar donde el código demuestra que es mergeable, no solo donde se afirma que lo es.
4. Coordinación de despliegue. En equipos serios, mergear ≠ deployar. El PR puede etiquetarse, asociarse a un release, posponerse para después de un freeze. Es el punto de control entre "el código está listo" y "el código va a producción".
Cuando un PR se hace bien, los cuatro trabajos se cumplen. Cuando se hace mal, normalmente es porque alguno se omitió: PRs sin descripción (mata #2), reviewers que solo dicen "LGTM" (mata #1), merges con CI rojo (mata #3), deploys los viernes a las 5pm (mata #4).
- Un PR sin descripción es deuda técnica disfrazada — vas a pagarla cuando alguien necesite entender por qué.
- Si tu equipo nunca rechaza un PR, no significa que escriben código perfecto. Significa que la review es ceremonia.
- CI verde no garantiza que el código es bueno. Garantiza que no es obviamente malo. La review es para lo no obvio.
Tu reviewer aprueba el PR diciendo "LGTM" sin más comentarios. CI está verde. ¿Qué problema potencial hay?
3. Dimensionar el impacto en la vida real
En clase los PRs pueden parecer un trámite. En la práctica, son la diferencia entre un equipo que entrega y uno que vive apagando incendios. Tres situaciones que pasan todo el tiempo:
El bug que un review hubiera detectado. Una desarrolladora cambia la lógica de cálculo de impuestos. Tests verdes (no había test que cubriera el caso de Costa Rica). Reviewer pregunta: "¿esto cubre los países donde el IVA depende del producto?". La autora se da cuenta de que no, refactoriza, agrega test. Costo: 20 minutos. Si se hubiera mergeado: facturas mal cobradas durante semanas hasta que un cliente se quejara.
El deploy roto un viernes. Hotfix urgente, mergeado sin esperar a CI. CI tarda 8 minutos. A los 6 minutos del merge, el sitio empieza a tirar 500. El developer pasa el fin de semana revirtiendo y comunicando con stakeholders. Si el repo hubiera bloqueado merges sin CI verde: nada de esto.
La decisión arquitectónica que sobrevivió 3 años. Un junior abre PR que mete una librería nueva. Senior comenta: "¿probaste con la stdlib? Esta lib agrega 200KB al bundle y no la mantienen activamente". Discusión en el PR, comparación, queda registrado por qué al final fueron con stdlib. Tres años después, otro dev quiere agregar la misma lib. Hace git log, llega al PR, lee la discusión, evita repetir el debate. El PR le ahorró media tarde de investigación.
Estas situaciones no son hipotéticas — son el día a día de cualquier equipo. Y todas se previenen con la misma herramienta: un PR bien hecho, leído por al menos una persona más, con CI verde antes de mergear.
- El costo de un buen PR es minutos. El costo de un PR malo se mide en horas, días o (en casos extremos) titulares de prensa.
- Knight Capital perdió USD 440M en 45 minutos por un deploy mal coordinado en 2012. No fue un PR — fue la ausencia del proceso que un PR enforza.
- En equipos remotos, el PR es el lugar de discusión técnica. Sin él, las decisiones se pierden en Slack y se evaporan al mes.
Tu equipo necesita hacer un hotfix urgente: un cliente importante reporta que no puede pagar. ¿Qué hacés?
4. Cuándo NO hacer un PR
Esta guía evangeliza los PRs, pero el dogma "todo via PR siempre" tampoco es real. Hay casos donde el PR agrega fricción sin agregar valor:
Repos personales sin colaboradores. Si el repo es tuyo, sos el único contributor, y nadie más va a leer la historia — push directo está bien. El PR brilla en colaboración; sin colaboración, es ceremonia.
Cambios triviales en docs personales. Typo en tu README, fix de un link roto en tu blog. Si rollback es trivial y no rompe nada operativo, podés saltarte el PR.
Hotfix con autorización explícita y proceso documentado. Equipos serios tienen un "break-glass procedure": si la app está caída y hay que arreglar ya, alguien con permisos puede pushear directo, pero queda registrado y se hace un post-mortem después. No es lo normal, es la excepción documentada.
Experimentos en branches aisladas que nunca van a main. Una rama de spike que vas a tirar — no necesita PR.
La regla práctica: si el código va a producción o a una branch que comparte con otros, va por PR. Todo lo demás es discusión caso por caso.
- Si tu equipo tiene "branch protection rules" en main (típico), físicamente no podés saltarte el PR aunque quieras.
- "Es urgente" rara vez es razón para saltar PR — casi siempre es razón para hacer un PR chico y enfocado y revisarlo rápido.
- Si te encontrás justificando muchos pushes directos, hay un problema de proceso, no de velocidad.
Trabajás solo en un proyecto pasion, repo privado, sin colaboradores. ¿Necesitás abrir PRs?
II · El flujo
5. Antes de empezar: branch limpia
El error más común en gente que empieza con PRs es trabajar directamente sobre main y darse cuenta tarde. Los dos hábitos que evitan el 80% de los problemas son: (1) arrancar desde una main actualizada, y (2) usar nombres de branch que comuniquen.
# 1. Asegurate de estar en main y de que está al día $ git checkout main $ git pull --rebase origin main # 2. Creá tu branch desde main, con nombre descriptivo $ git checkout -b feat/add-stripe-payments # Anti-pattern: branches genéricas o con tu nombre $ git checkout -b cesar-branch # ❌ no $ git checkout -b fix # ❌ tampoco
Convenciones de nombre populares: feat/... (feature nueva), fix/... (bugfix), chore/... (mantenimiento), refactor/... (sin cambio funcional), docs/.... No es regla universal — usá lo que tu equipo use.
- Si tu equipo usa Linear/Jira, incluí el ticket:
feat/PROJ-123-add-stripe-payments. Linkea automáticamente. - Branches que vivieron más de una semana son un olor. Si el cambio es grande, dividilo en PRs incrementales.
- Después de mergear, borrá la branch (GitHub lo ofrece con un click). Branches viejas sin tracking son ruido visual.
Vas a arreglar un bug en el carrito de compras. ¿Qué nombre de branch elegís?
6. Mientras trabajás: commits que cuentan una historia
Un commit no es un "guardado". Es una unidad de cambio coherente y revertible. La pregunta que decide si algo merece ser un commit es: "¿tendría sentido revertir solo esto?". Si la respuesta es sí, va en su propio commit.
Los commits atómicos hacen tres cosas: facilitan la review (un cambio = un foco), permiten revertir granularmente (rollback quirúrgico, no a martillazos), y dejan una historia que se puede leer un año después y entender qué pasó.
El otro frente es el mensaje. La fórmula que funciona: verbo en infinitivo + qué cambia + por qué (si no es obvio). El "por qué" es lo más valioso — el "qué" se puede inferir del diff, el "por qué" no.
# ❌ Commits que NO comunican git commit -m "fix" git commit -m "wip" git commit -m "more changes" git commit -m "asdf" # ✅ Commits que comunican git commit -m "Validate cart quantity is positive before checkout" git commit -m "Extract Checkout payload validation into FormRequest" # ✅ Commit con cuerpo (cuando el por qué importa) git commit -m "Use Decimal for tax calculation" -m "Float arithmetic was producing 0.299999... in receipts. Decimal preserves precision and matches what the legal team expects."
Si arrancás un trabajo y hacés 8 commits con mensajes confusos, no entres en pánico — antes de abrir el PR podés "limpiar" la historia con git rebase -i HEAD~8 y reescribir o juntar commits. El PR final puede tener 3 commits limpios aunque los hayas trabajado en 20.
- Si tu mensaje empieza con "fix" sin más contexto, falta información. Fix what? Fix why?
- Si vas a juntar todos los commits con squash al mergear, igual hacé commits decentes durante el trabajo — el squash final lo hace una sola persona, los commits los leés vos durante el desarrollo.
- Convencional:
type(scope): description(Conventional Commits). Útil si tu equipo lo adoptó o si automatizás changelogs.
Hiciste 5 commits con mensajes "wip", "fix", "more", "fix2", "done". Vas a abrir el PR. ¿Qué hacés?
7. Abriendo el PR: título, descripción y estado
Un PR bien abierto se revisa más rápido y más profundo. Tres elementos importan más de lo que parece:
Título. Es lo primero (a veces lo único) que ven tus compañeros. Mismo principio que los commits: verbo + qué + scope si ayuda. "Add Stripe payments to checkout" > "PR #42" > "changes".
Descripción. El body del PR es el lugar para explicar el contexto que el código no puede explicar solo: por qué este approach y no otro, qué quedó fuera de scope, qué riesgos hay, cómo testear. Una buena descripción ahorra horas de ida y vuelta.
Estado. Si todavía estás trabajando, abrí como Draft. Eso señaliza "no me revisen aún, pero pueden ver el progreso". Cuando esté listo, lo marcás como Ready for review.
# Plantilla de descripción que escala bien: ## Resumen Agrega procesamiento de pagos con Stripe en el checkout. Closes #123. ## Cambios - Endpoint POST /api/checkout/charge - Servicio StripeGateway con retry y manejo de errores - UI de confirmación con loading state ## Decisiones - Stripe vs PayPal: Stripe tiene mejor SDK para nuestro stack y soporte SV. - Sync vs async: por ahora sync, async cuando agreguemos suscripciones. ## Cómo probar 1. stripe listen --forward-to localhost:3000/webhook 2. npm run dev y ir a /checkout 3. Usar tarjeta de prueba 4242 4242 4242 4242 ## Out of scope - Refunds (PR siguiente) - Suscripciones (Q3)
GitHub permite tener una plantilla de PR en .github/PULL_REQUEST_TEMPLATE.md. Si tu equipo la tiene, aparece auto-completada cuando abrís un PR. Si no la tiene, proponé una.
- PRs sin descripción son la cuarta causa más común de retraso en review (después de tamaño, hora del día y reviewer asignado).
- Un screenshot/GIF del cambio visual ahorra páginas de explicación. Cmd+Shift+5 en Mac, captura, drag al PR.
- Si tu PR cambia más de 400 líneas, considerá dividirlo. La calidad de la review baja exponencialmente con el tamaño.
¿Cuál de estas descripciones de PR es más útil para un reviewer que va a invertir 30 minutos?
8. Recibiendo review: cómo responder sin que duela
La parte más incómoda del PR para mucha gente: alguien dejó 8 comentarios y uno dice "Request changes". El instinto es defensivo. La mejor práctica es lo contrario: tratar cada comentario como evidencia de que alguien invirtió tiempo en mejorar tu código.
No estás siendo evaluado, está siendo evaluado el código. Es una distinción que cuesta interiorizar pero cambia todo. "Request changes" no es un ataque personal — es el botón que GitHub provee para señalar bloqueos.
Tres tipos de comentarios y cómo responder a cada uno:
# Tipo 1: Bug o problema real # Reviewer: "Esta función no maneja el caso de array vacío, va a crashear." Respuesta: arreglar + commitear + responder corto. # Tipo 2: Sugerencia / preferencia # Reviewer: "Preferiría usar map en vez de forEach acá." Respuesta: aceptar O explicar por qué no, con argumento. # Tipo 3: Pregunta / pedido de aclaración # Reviewer: "¿Por qué tax_rate hardcodeado a 0.13?" Respuesta: contestá la pregunta, dejá la respuesta visible. # Anti-pattern Resolver comentarios sin responder = ❌
Una herramienta útil: GitHub permite responder con "suggested change". El reviewer escribe el código sugerido en un bloque, vos podés aplicarlo con un click. Si todas las sugerencias son triviales, lo resolvés en un minuto.
- Si te frustra recibir review, probablemente sea señal de que el cambio era más grande o más complejo de lo que pensabas. PRs chicos = reviews chicas.
- El silencio del reviewer no es aprobación. Si nadie comenta en 24h, es OK pingear: "¿lo ves esta semana o lo paso a otra persona?".
- Reviewers que solo aprueban sin comentarios: es válido pedir más feedback explícitamente. "¿Pudiste mirar la lógica de X?" abre la puerta.
Tu reviewer dejó 12 comentarios y "Request changes". Te sentís atacado. ¿Qué hacés?
9. Dando review: cómo no ser el revisor odioso
Hacer una buena review es un skill subestimado. La mayoría se va a uno de dos extremos: nitpicker (300 comentarios sobre formato, ningún comentario sobre arquitectura) o rubber-stamper (apruebo todo, "looks good"). Ambos son inútiles.
Una review útil prioriza: (1) bugs y seguridad primero, (2) arquitectura y diseño después, (3) legibilidad y mantenibilidad en tercer lugar, y (4) estilo y formato último (idealmente automatizado con linter).
El otro principio: el tono importa más que la corrección. Tener razón con tono agresivo es perder. Tener razón con tono curioso es educar.
# ❌ Comentario odioso "Esto está mal. Cambialo." # ✅ Mismo problema, comentario que invita a discusión "Acá veo que usás X — ¿probaste con Y? El issue con X es Z. Si Y no aplica por alguna razón, puede ser bueno dejar un comment." # Etiquetas que ayudan a clasificar la urgencia "nit: typo en el comentario" # no bloquea "question: ¿por qué async acá?" # pide info "suggestion: extraer a helper" # proponer, no exigir "blocking: esto causa NPE en producción" # sí bloquea
Otro tip: si vas a hacer "Request changes", combinalo siempre con un comentario que explique qué tiene que cambiar para que apruebes. "Request changes" sin contexto frustra y demora.
- Si tu review tiene más de 15 comentarios y la mayoría son nits, considerá dejar la review en "Comment" en vez de "Request changes" — no merece bloqueo.
- Reviewar un PR de 800 líneas en 5 minutos no es review, es ceremonia. Si no tenés tiempo, decilo: "puedo en 2 horas, ¿esperás o paso a otra persona?".
- Conventional Comments (https://conventionalcomments.org) tiene un vocabulario chico que ayuda a clasificar. Vale la pena adoptarlo en equipo.
Encontraste un bug claro pero también 6 nits de formato. ¿Cómo dejás la review?
10. Mergeando: squash, merge o rebase
GitHub te ofrece tres botones para mergear: Merge commit, Squash and merge, y Rebase and merge. Cada uno produce una historia distinta. Cuál elegir depende de qué historia quiere tu equipo.
Squash and merge (más común): junta todos los commits del PR en uno solo y lo agrega a main. Historia ultra limpia: 1 PR = 1 commit. Perdés los commits intermedios. Bueno cuando los commits del PR no aportan valor histórico individualmente.
Merge commit: agrega los commits del PR tal cual + un "merge commit" que une las dos branches. Conserva todo el detalle. La historia es más rica pero menos lineal. Bueno cuando los commits cuentan una progresión real.
Rebase and merge: aplica los commits del PR uno por uno encima de main, sin merge commit. Historia lineal y detallada. Útil para ciertos workflows pero rompe los SHAs originales — los reviewers pueden perder contexto.
# Cómo elegir (rule of thumb) PR pequeño / focal → Squash and merge ✅ PR de feature compleja → Merge commit ✅ Hotfix de 1 línea → Squash and merge ✅ Refactor en pasos → Merge commit ✅ Cambios masivos / drift → Rebase and merge ⚠️ # Quién aprieta el botón El autor del PR, después de approval + CI verde. Excepción: el autor está OOO → un reviewer mergea con permiso explícito.
Después del merge, GitHub ofrece "Delete branch". Hacé click. Branches mergeadas y no borradas son ruido. La historia queda en el PR y en main; la branch ya cumplió su función.
- Squash es el default seguro si tu equipo no tiene preferencia explícita. La historia limpia se mantiene fácil.
- Si tu repo usa
maincomo source of truth para deploys (CD), pensá cada merge a main es un release potencial. Esa mentalidad cambia cómo escribís commits. - Algunos equipos protegen main: solo merge si CI verde + N approvals + branches up-to-date. Configurable en GitHub: Settings → Branches.
Tu PR tiene 5 commits que cuentan una refactorización en pasos: "extract", "add tests", "remove old", "wire", "cleanup". ¿Qué estrategia?
III · Cuando algo se rompe
11. main avanzó mientras trabajabas
Abrís el PR y GitHub te dice "This branch is out-of-date with the base branch". O al pushear ves ! [rejected] feature/x -> feature/x (fetch first).
Mientras vos trabajabas en tu branch, alguien mergeó otro PR a main. Tu branch ya no parte del último commit; parte de uno viejo. Tenés que traer esos commits nuevos a tu branch antes de seguir.
Hay dos formas de hacerlo: merge (crea un commit de merge) o rebase (reaplica tus commits encima de main). Las dos llegan al mismo resultado funcional pero con historias distintas.
# Paso 0: asegurate de que tu trabajo está commiteado $ git status # Paso 1: traer los cambios de main $ git fetch origin main # Paso 2A: REBASE (recomendado para branches personales) $ git rebase origin/main # Paso 2B: MERGE (si tu branch ya tiene PR con reviews) $ git merge origin/main # Si hicieron rebase, el push necesita force (con cuidado): $ git push --force-with-lease
Regla práctica: rebase mientras nadie más usa tu branch. Si ya hay reviewers comentando, usá merge — el force-push borra los SHAs viejos y los comentarios quedan "huérfanos" en líneas que ya no existen.
- GitHub muestra el banner amarillo "Update branch" en el PR.
- El botón verde de merge aparece deshabilitado o el repo tiene "require branches up to date" activo.
git pushfalla con(non-fast-forward).
git rebase de un branch que otros también tienen checkeada. Reescribís SHAs y la próxima persona que haga pull va a ver un caos. Para branches compartidas, merge.Tu PR tiene 3 reviewers que ya dejaron 12 comentarios en líneas específicas. main avanzó. ¿Rebase o merge?
12. Conflicto de merge
Hiciste git merge o git rebase y git te dice CONFLICT (content): Merge conflict in src/foo.ts. Al abrir el archivo ves bloques con <<<<<<<, =======, >>>>>>>.
Un conflicto ocurre cuando git no puede decidir solo qué versión de una línea conservar. Las dos ramas modificaron el mismo lugar de formas distintas, y git te pide que decidas vos.
Los markers no son mágicos: son texto que git inyecta en el archivo. La parte entre <<<<<<< HEAD y ======= es tu versión (la rama actual). La parte entre ======= y >>>>>>> es la otra versión (la que estás trayendo).
# Después del CONFLICT, ves el estado: $ git status Unmerged paths: both modified: src/foo.ts # Dentro de src/foo.ts vas a ver algo así: <<<<<<< HEAD const total = price * 1.13; // IVA SV ======= const total = price * 1.16; // IVA MX >>>>>>> origin/main # Editás el archivo a mano dejando solo lo correcto: const total = price * (country === 'SV' ? 1.13 : 1.16); # Marcás como resuelto y commiteás: $ git add src/foo.ts $ git commit # o: git rebase --continue # ¿Te arrepentiste y querés salir del lío? $ git merge --abort # o: git rebase --abort
Si el conflicto es trivial (formato, espacios), tu IDE suele tener una UI de "Accept incoming" / "Accept current" / "Accept both". Si el conflicto es lógico (dos cambios reales en la misma línea), parate, leelo, y decidí qué mantener — no acepts mecánicamente.
- CI falla con errores de sintaxis raros que no existían antes — probablemente quedó un marker en el código.
- Después de "resolver" un conflicto, el comportamiento de la feature cambió. Releé el diff antes de pushear.
- Hay muchos conflictos en cada merge. Síntoma de que la branch vivió demasiado tiempo — mergeá más seguido.
Resolviste un conflicto, hiciste git add y git commit, pero CI falla con Unexpected token <. ¿Qué pasó?
13. Algo salió mal: deshacer cosas
Mergeaste un PR que rompió producción. O hiciste reset --hard y borraste trabajo. O committeaste a la branch equivocada. Necesitás volver atrás sin romper más cosas.
Git rara vez borra cosas para siempre. Casi todo se puede recuperar si actuás antes de los ~90 días que dura el reflog. La clave es elegir la herramienta correcta para cada situación.
Tres conceptos: revert (crea un commit nuevo que deshace), reset (mueve el puntero hacia atrás, opcionalmente borra cambios), reflog (el historial local de a dónde apuntó HEAD en los últimos días — tu red de seguridad).
# Caso 1: mergeaste algo a main que rompió prod $ git revert <sha-del-merge> $ git push origin main # Caso 2: committeaste a main en vez de a tu feature branch $ git branch feature/x # marca tu commit en una branch nueva $ git reset --hard HEAD~1 # mueve main un commit atrás $ git checkout feature/x # Caso 3: hiciste reset --hard y perdiste trabajo. NO entres en pánico. $ git reflog abc1234 HEAD@{0}: reset: moving to HEAD~3 def5678 HEAD@{1}: commit: trabajo importante # Lo recuperás: $ git reset --hard def5678 # Caso 4: hiciste force-push y querés volver al push anterior $ git push --force-with-lease origin <sha-viejo>:<branch>
Regla: en branches compartidas (main, develop) usá revert. Es un commit más, no reescribe historia, todos pueden seguir trabajando sin pullear nada raro. reset es para tus branches locales antes de pushear.
- Después de un
reset --hardsentís pánico — el reflog va a salvarte.git reflogprimero, respirás después. - Querés "deshacer un merge" en main: la respuesta es siempre
git revert -m 1 <sha>, nuncareset. - Te avergüenzan los commits con typos:
git commit --amendantes de pushear; después, dejalos vivir.
git reset --hard de commits que ya pusheaste a una branch compartida. La gente que pulleó esa branch va a tener un dolor de cabeza imposible de explicar. revert siempre en branches compartidas.Mergeaste el PR #142 a main y rompió producción. El equipo necesita arreglo en 5 minutos. ¿Qué hacés?
IV · Cierre
14. Anti-patterns: lo que mejor no hacer
Después de leer todo lo anterior, esta lista es casi redundante. Pero merece estar acá porque son cosas que veo todo el tiempo, y cada una se siente "razonable" en el momento. Identificarlas por nombre ayuda a pararse a tiempo.
# ❌ Force-push a main $ git push --force origin main # ❌ Mega-PR de 2000 líneas $ git diff main feature/x --stat # 47 files, +2103 -891 # ❌ "Fix typo" sin contexto $ git commit -m "fix typo" # ❌ Mergear con CI rojo "porque sé que es flaky" CI status: ❌ failing — Override and merge anyway? [Y/n] # ❌ Auto-aprobar tu propio PR para mergear más rápido Approved by: @yourself ✓ # ❌ Reviews de "LGTM" en cambios no triviales Reviewer: "LGTM 👍" (en un PR de 600 líneas tocando auth) # ❌ Discusión técnica importante en Slack DM Slack DM: "che, mejor uses Redis acá porque..." → decisión perdida # ❌ Deploy los viernes a las 5pm sin necesidad Friday 17:00 → push to main → deploy → weekend incident
La mayoría de estos anti-patterns aparecen bajo presión (urgencia, cansancio, deadline). El proceso del PR existe justamente para protegerte de tu propia presión: aún cuando creés que "esta vez está justificado saltarse el paso", la respuesta casi siempre es no.
- Si tu equipo discute mucho "pero esta vez es distinto", revisen el proceso — debería haber excepciones documentadas, no negociadas caso por caso.
- PRs grandes son síntoma de scope creep. Si el cambio creció, paralo, divide, mergeá lo que esté listo, seguí en otro PR.
- "Fix typo" sin contexto se vuelve invisible para tu yo del futuro. Cualquier commit merece 5 segundos extra.
Tu PR tiene un test que falla intermitentemente. CI rojo. ¿Qué hacés?
15. Cómo se ve un buen PR un año después
Una forma de saber si un PR está bien hecho: imaginalo dentro de un año, cuando otra persona haga git blame sobre una línea rara y aterrice ahí. ¿Qué encuentra?
Un mal PR un año después: título "fix", descripción vacía, 23 commits con mensajes "wip", "more", "fix2", review de un solo "LGTM". El nuevo dev no entiende por qué se hizo, qué alternativas se descartaron, ni si hay efectos secundarios. Termina haciendo arqueología en Slack o re-implementando desde cero por miedo a romper algo.
Un buen PR un año después: título descriptivo, descripción que explica el porqué, decisiones documentadas (incluyendo lo que no se hizo y por qué), 4 commits con mensajes coherentes, una conversación de review donde otra persona preguntó algo no obvio y la autora respondió con argumento. El nuevo dev entiende el contexto en 5 minutos y puede tomar una decisión informada sobre cómo modificar el código.
La diferencia entre uno y otro es 15 minutos extra al abrir el PR y 10 minutos más respondiendo reviews. Esa inversión paga 10x cuando alguien (vos mismo, probablemente) tiene que volver al código.
Pensá en cada PR como una carta a tu yo del futuro — o al desarrollador que llegue después de vos. No tenés que hacer un essay; basta con ser explícito sobre el qué, el por qué, y lo que no hiciste. La historia de un proyecto es la suma de sus PRs leídos en orden. Hacé que la tuya valga la pena leer.
Y si te quedaste con dudas sobre algún escenario específico, los enlaces de "Para profundizar" más abajo cubren los temas con más detalle del que cabe en esta guía.
- Cuando hagas
git blameen un código del año pasado y agradezcas la descripción del PR — replicalo en el tuyo. - Si tu PR fue mergeado con cero comentarios, está bien si es trivial. Si era complejo, considerá si la review fue real o ceremonia.
- Los buenos equipos invierten en post-mortems de PRs problemáticos. Aprenden del proceso, no solo del código.
Vas a abrir un PR para una refactorización de 4 archivos. Tenés 10 minutos antes de una reunión. ¿Qué hacés?
Para ir más lejos
Si querés ir más profundo:
- Scott Chacon. Pro Git (2.ª edición, gratuito en git-scm.com/book) — capítulos 3 (Branching) y 7 (Tools, incluye reflog y bisect).
- GitHub Docs. About pull requests — docs.github.com/en/pull-requests.
- Julia Evans. How Git Works (zine, pago) y los blog posts gratuitos en jvns.ca — explicaciones visuales fenomenales.
- Atlassian. Merging vs Rebasing — tutorial visual que vale los 10 minutos.