2009-11-04 11 views
17

Estoy intentando fusionar 2 ramas que tienen muchos cambios en ellas, varias con conflictos de combinación. Combiné los archivos usando git mergetool, pero posteriormente me di cuenta de que fusioné un par de ellos de forma incorrecta. Básicamente, quiero volver al estado en conflicto para esos archivos de pareja, por lo que puedo volver a ejecutar la herramienta de mezcla y corregir mis errores. No quiero tirar toda mi fusión, ya que la mayor parte es correcta.¿Cómo recupero mis conflictos de fusión de git después de fusionarlos incorrectamente?

He intentado restablecer a mi cabeza y luego hacer git checkout -m other_branch -- my_file en vano. Terminé reiniciando a HEAD, sacando el archivo de la otra rama y simplemente haciendo git add --patch en el archivo, solo organizando lo que quería. Pero tiene que haber una mejor manera ...

Respuesta

12

puedes descubrir si ha entrado en conflicto estado en el índice (antes de restablecer a la cabeza), a través de

$ git ls-files --stage --abbrev my_file 

Usted debe obtener algo como lo siguiente:

100644 257cc56 1  my_file 
100644 b7d6715 2  my_file 
100644 5716ca5 3  my_file 

Si no lo obtiene, deberá usar git update-index, como Charles Bailey said, o usar archivos temporales. Si tiene eso, entonces

$ git checkout -m my_file 

debería funcionar (lo he comprobado).

+0

acaba de intentar '-m' git checkout y funciona incluso si solo me dan un uno por etapas versión de archivo (es decir, después de' git add' o el uso con éxito de 'mergetool' GIT). Tal vez esa es una característica más nueva de Git (estoy usando 2.1.3). – siegi

6

Usted puede hacer esto con git update-index usando las --cacheinfo o --index-info opciones para eliminar la entrada 0 en el índice para un archivo dado y poblar las entradas 1, 2 y 3 con las versiones base, local y remota, respectivamente, pero va a ser complicado.

Probablemente va a ser más fácil extraer las distintas versiones en archivos temporales y ejecutar manualmente la herramienta de fusión, escribir la respuesta en el archivo correcto y agregar el resultado de la fusión exitosa.

p. Ej.

git show $(git merge-base HEAD MERGE_HEAD):file >base-file 
git show HEAD:file >local-file 
git show MERGE_HEAD:file >remote-file 

Run mergetool manualmente, escribiendo a file.

git add file 
0

Se puede utilizar:

git checkout [--ours|--theirs|--merge] <paths> 

a la comprobación de la ruta (s) que se encuentran en la rama que se fusionaron en o desde o para recrear la fusión en conflicto.

La página de git-checkout tiene un poco más sobre este tema.

Como Charles Bailey señaló que esto no funciona cuando el archivo fusionado ya se ha agregado al índice. He jugado un poco y aquí es un script que debe hacer el trabajo:

#!/bin/bash 
# 
# Distributed under the GNU General Public License, version 2.0. 
# 
# git-goat: 
# 
# Restore a merge conflict, after it has already been resolved. 

# Lifted from contrib/completion/git-completion.bash 
__gitdir() 
{ 
    if [ -z "${1-}" ]; then 
     if [ -n "${__git_dir-}" ]; then 
      echo "$__git_dir" 
     elif [ -d .git ]; then 
      echo .git 
     else 
      git rev-parse --git-dir 2>/dev/null 
     fi 
    elif [ -d "$1/.git" ]; then 
     echo "$1/.git" 
    else 
     echo "$1" 
    fi 
} 

into=$(git describe --all HEAD) 
from=$(cat $(__gitdir)/MERGE_HEAD) 
base=$(git merge-base $into $from) 

case "$1" in --ours|--theirs|--merge) whose=$1; shift; esac 

[ -z "$1" ] && echo "fatal: at least one file has to be specified" && exit 

for file in "[email protected]" 
do 
    (
     echo -e "0 0000000000000000000000000000000000000000\t$file" 
     git ls-tree $base $file | sed -e "s/\t/ 1\t/" 
     git ls-tree $into $file | sed -e "s/\t/ 2\t/" 
     git ls-tree $from $file | sed -e "s/\t/ 3\t/" 
    ) | git update-index --index-info 
    git checkout ${whose:-"--merge"} $file 
done 

Tenga en cuenta que no he probado esto mucho. Si encuentra algún problema o tiene otras mejoras, here es una "esencia" tenedorable.

+1

Es digno de mención que esto solo funciona si no saliste de la herramienta de mergeo, guardando "con éxito" ya que esto hace que mergetool 'agregue' el archivo resuelto y elimine las entradas en conflicto del índice. –

+0

Charles Bailey, ¿estás seguro de que lo que dices es correcto? El script para mí parece exactamente restaurar el índice al estado/before/add. No se está refiriendo a: {1,2,3}: inicialmente, sino más bien dirigiendo los commits a través de HEAD, MERGE_HEAD y 'merge-base ...'. –

+0

@TilmanVogel: compruebe la versión de la respuesta que comento, no la actualización en respuesta a mi comentario. –

0

Si acepta accidentalmente que diga sí al aviso de conflicto solucionado sin guardar los cambios de mergetool, creo que puede ocultar los cambios efectuados y rehacer la fusión.

git stash 
git merge <other branch> 
Cuestiones relacionadas