refactor: update merge conflict detection strategy (merge --no-commit to merge-tree --write-tree) #72

Merged
jt merged 1 commits from refactor/merge-conflict-detections into main 2026-10-01 02:54:25 +00:00
2 changed files with 16 additions and 11 deletions
+3 -8
View File
@@ -75,17 +75,12 @@ def show_commits_to_merge(target):
def check_merge_conflicts(target: str): def check_merge_conflicts(target: str):
merge_conflicts = Git("merge", target, ff=False, commit=False).code( merge_conflicts = Git.get_merge_conflicts(target, print="Verificando conflictos de merge")
print="Realizando merge de prueba para verificar conflictos"
)
# Si el merge no llegó a realizarse (por ejemplo, "Already up to date") no hay nada que abortar
if Git.is_merging():
Git("merge", abort=True).exec(print="Abortando merge de prueba")
if merge_conflicts: if merge_conflicts:
files = "\n".join(" - " + file for file in merge_conflicts)
base.io_error( base.io_error(
f"La rama actual tiene conflictos con {target}.\n" f"La rama actual tiene conflictos con {target}:\n{files}\n\n"
f"Se recomienda mergear {target} a la rama actual, resolver los conflictos localmente,\n" f"Se recomienda mergear {target} a la rama actual, resolver los conflictos localmente,\n"
"y ejecutar nuevamente este comando", "y ejecutar nuevamente este comando",
title="Conflictos de merge", title="Conflictos de merge",
+13 -3
View File
@@ -64,9 +64,19 @@ class Git:
return Git._get_references("heads/" + prefix) return Git._get_references("heads/" + prefix)
@staticmethod @staticmethod
def is_merging() -> bool: def get_merge_conflicts(target: str, print: str | None = None) -> list[str]:
"""Indica si hay un merge en curso (existe MERGE_HEAD), con o sin conflictos.""" """Archivos con conflictos al mergear target en HEAD. El merge se resuelve en memoria con
return Git("rev-parse", "MERGE_HEAD", quiet=True, verify=True).code() == 0 merge-tree, sin tocar el índice ni el worktree."""
process = Git(
"merge-tree", "HEAD", target, write_tree=True, name_only=True, messages=False
)._get(print, check=False)
# 0: sin conflictos, 1: con conflictos, otro: error (por ejemplo, historias sin relación)
if process.returncode not in (0, 1):
process.check_returncode()
# Primera línea: OID del árbol resultante, luego los archivos en conflicto
return [l for l in process.stdout.splitlines()[1:] if l]
@staticmethod @staticmethod
def status(): def status():