Checklist de Resolución de Conflictos de Merge
Un manual paso a paso para resolver conflictos de merge o rebase de forma segura. Ejecuta los pasos en orden -- saltarse adelante es cómo se pierden los árboles de trabajo limpios. Cada paso tiene una salida de emergencia (--abort) así que puedes retroceder en cualquier momento hasta el commit final.
Cómo Usar Este Checklist
- Trata cada paso como un punto de control. No inicies el paso N+1 hasta que el paso N esté completado.
- Si algo se ve mal (trabajo sin commit, archivos sorpresa, una rama desconocida), DETENTE y ejecuta el paso 18 (
--abort). - La mayoría de conflictos se resuelven en los pasos 8-13. Los pasos 1-7 previenen conflictos; los pasos 14-20 verifican la resolución.
Fase 1: Preparación (Pasos 1-5)
Haz todo esto ANTES de iniciar el merge o rebase. Saltarse la preparación es la #1 causa de desastres de "perdí mis cambios".
1. Asegúrate de que tu árbol de trabajo esté limpio
git statusSi algo está staged o modificado, haz commit, stash o descárdalo. Nunca inicies un merge con un árbol sucio -- los conflictos mezclarán tu trabajo en progreso con la resolución del merge y no podrás diferenciarlos.
# Haz stash si quieres guardar trabajo en progreso
git stash push -u -m "wip before merging main"2. Confirma que estás en la rama correcta
git branch --show-currentHaces merge EN la rama actual. Si estás a punto de ejecutar git merge main, deberías estar en tu rama de feature -- no en main mismo.
3. Actualiza ambas ramas desde el remote
git fetch origin
git pull --ff-only origin <your-branch>Un conflicto resuelto contra un main anticuado es trabajo desperdiciado -- los conflictos reales aún están adelante. --ff-only rechaza hacer merge silenciosamente si tu rama ha divergido.
4. Decide: merge o rebase
| Situación | Usa |
|---|---|
| Rama de feature ya enviada y compartida | git merge main (preserva historial) |
| Rama personal, aún no enviada (o fuerzas push de tus propias ramas) | git rebase main (historial lineal) |
| Tirando cambios de compañero de equipo a tu rama | git pull --rebase si tienes commits locales, plain git pull de otro modo |
Si no estás seguro, usa merge. Es más difícil perder trabajo con un merge.
5. Anota tu commit de inicio (tu ancla de seguridad)
git rev-parse HEAD
# escribe este SHA en algún lugar -- una nota adhesiva, un archivo temporal, donde seaSi todo sale mal, git reset --hard <that-sha> te pone de vuelta exactamente donde empezaste. git reflog también funciona, pero un SHA escrito es más rápido bajo estrés.
Fase 2: Activar el Merge (Pasos 6-7)
6. Ejecuta el comando merge o rebase
# Enfoque merge
git merge main
# O enfoque rebase
git rebase mainSi no hay conflictos, estás listo -- salta al paso 19.
7. Lee la salida antes de hacer nada más
Git imprime exactamente qué archivos tienen conflicto y qué tipo de conflicto es cada uno (contenido vs. add/add vs. delete/modify). Lee esta lista. No inicies a abrir archivos hasta que sepas cuántos conflictos tienes y dónde están.
git status
# Busca "Unmerged paths" -- esa es tu lista de trabajo# Obtén una lista limpia solo de archivos en conflicto
git diff --name-only --diff-filter=UFase 3: Entiende Cada Conflicto (Pasos 8-10)
Resuelve primero los conflictos más simples para reducir la superficie. Guarda los complicados para el final cuando tengas momentum.
8. Abre el primer archivo en conflicto y lee los marcadores
Los marcadores de conflicto se ven así:
<<<<<<< HEAD
tu versión (la rama en la que estás haciendo merge)
=======
su versión (la rama de la que estás haciendo merge)
>>>>>>> main
Durante un rebase, las etiquetas se invierten: HEAD es la rama base a la que estás rebaseando, y el lado >>>>>>> es tu commit entrante. Esto sorprende a todos al menos una vez.
9. Mira ambos lados en contexto, no solo el diff
# Muestra el diff completo con ambos lados
git diff
# O para un archivo específico
git diff -- path/to/file.ts
# Mira quién escribió cada lado y por qué
git log --merge --oneline -- path/to/file.ts
git log -p HEAD..MERGE_HEAD -- path/to/file.tsSaber por qué cada lado hizo un cambio -- no solo qué cambió -- es la diferencia entre una resolución real y una adivinanza que compila.
10. Decide la estrategia de resolución para este archivo
Elige una antes de editar:
| Estrategia | Cuándo |
|---|---|
| Mantén el nuestro | Su cambio es irrelevante para tu rama |
| Mantén el suyo | Tu cambio ahora es redundante (p. ej., hicieron lo mismo) |
| Combina ambos | Ambos cambios son necesarios y no chocan semánticamente |
| Reescribe | Ambos lados están mal ahora, dado que el otro lado existe |
# Toma un lado completamente
git checkout --ours path/to/file.ts
git checkout --theirs path/to/file.tsFase 4: Edita y Stagea (Pasos 11-13)
11. Edita el archivo: elimina los marcadores, escribe la resolución
Elimina cada línea <<<<<<<, =======, y >>>>>>>. El archivo debería compilar y leer naturalmente como si nunca hubiera estado en conflicto.
Un error común es dejar marcadores rezagados en partes del archivo sin tocar. Búscalos:
grep -rn '<<<<<<<\|=======\|>>>>>>>' .12. Ejecuta el archivo a través de sus herramientas
Para cada archivo resuelto, ejecuta lo que sea rápido y local:
# Verificación de tipos
npx tsc --noEmit
# Formato
npx prettier --write path/to/file.ts
# Lint
npx eslint path/to/file.tsSi un Server Component y un Client Component se importan mutuamente después de hacer merge, arregla la frontera ahora -- no después de stagear.
13. Stagea el archivo resuelto
git add path/to/file.tsPara un rebase, git add NO progresa automáticamente -- aún necesitas el paso 16. Para un merge, stagear todos los conflictos te deja listo para hacer commit.
Repite los pasos 8-13 para cada archivo en git status.
Fase 5: Verifica (Pasos 14-17)
14. Confirma que cero conflictos permanecen
git statusCada archivo bajo "Unmerged paths" debe desaparecer. Si git diff --name-only --diff-filter=U no devuelve nada, estás limpio.
15. Ejecuta la suite de construcción y pruebas completa
npm run build
npm run typecheck
npm testUn merge que compila archivos individuales pero rompe la construcción es el resultado más común de un mal merge. Atrápalo ahora, no en CI.
16. Continúa el rebase (solo rebase)
git rebase --continueSi aparecen más conflictos, ahora estás resolviendo los conflictos del SIGUIENTE commit. Vuelve al paso 8 para cada uno.
17. Verificación de cordura del diff final
# Para un merge: ¿qué contendrá el commit de merge?
git diff HEAD
# Para un rebase: ¿cómo difiere mi rama de antes?
git range-diff <starting-sha>..ORIG_HEAD <starting-sha>..HEADSi el diff tiene archivos que no tocaste o no esperas, algo salió mal. Detente e investiga antes de hacer commit.
Fase 6: Termina o Retrocede (Pasos 18-20)
18. Comando de retroceso si algo se siente mal
En CUALQUIER punto antes del commit final, puedes volver al estado del paso 1:
git merge --abort
git rebase --abortSi ya hiciste commit y necesitas deshacer:
git reset --hard <starting-sha-from-step-5>No hay vergüenza en retroceder. Un re-intento limpio es más rápido que desenredar un merge medio roto.
19. Completa el merge o rebase
# Merge: commit el merge con el mensaje auto-generado (o escribe el tuyo)
git commit
# Rebase: debería estar ya hecho después del --continue finalPara un commit de merge, escribe un cuerpo que explique cuáles fueron los conflictos y cómo los resolviste. El tú futuro te lo agradecerá durante un bisect.
20. Push -- cuidadosamente
# Merge: push regular está bien
git push
# Rebase: force-push, pero SOLO a tus propias ramas y SOLO con --force-with-lease
git push --force-with-lease--force-with-lease rechaza el push si alguien más hizo commit a la rama remota desde tu última fetch -- es la diferencia entre reescribir tu propio historial y sobrescribir el commit de un compañero. Nunca --force (sin -with-lease) en una rama compartida.
Referencia Rápida: Hoja de Trucos de Retroceso
| Estás en... | Sal con... |
|---|---|
| En medio de merge, conflictos sin resolver | git merge --abort |
| En medio de rebase, conflictos sin resolver | git rebase --abort |
| Ya hiciste commit del merge, te arrepientes | git reset --hard ORIG_HEAD |
| Ya hiciste push de un mal merge | git revert -m 1 <merge-sha> (NO hagas force-push para deshacer) |
| Perdiste el rastro completamente | git reflog -- encuentra el SHA de antes, luego git reset --hard <sha> |
Errores Comunes
- Resolviendo conflictos en una base anticuada. Siempre haz pull de
mainprimero (paso 3). Resolver contra elmainde la semana pasada significa hacer el trabajo dos veces. - Mezclando tu trabajo en progreso en la resolución. Un árbol sucio al inicio de un merge es un bug garantizado. Haz stash primero (paso 1).
- Confundiendo "ours" y "theirs" durante un rebase. Se invierten. Cuando tengas dudas, mira
git logpara confirmar qué commit es cuál. - Haciendo commit con marcadores aún en el archivo. Siempre busca
<<<<<<<antes de stagear. - Haciendo force-push de una rama compartida. Usa
--force-with-lease, y nunca enmain.