Pregunta Cómo resolver conflictos de fusión en Git


¿Hay una buena manera de explicar cómo resolver conflictos de fusión en Git?


4123
2017-10-02 11:31


origen


Respuestas:


Tratar: git mergetool

Abre una GUI que lo guiará a través de cada conflicto y podrá elegir cómo fusionarse. Algunas veces se requiere un poco de edición manual luego, pero por lo general es suficiente por sí mismo. Es mucho mejor que hacer todo a mano ciertamente.

Según el comentario de @JoshGlover:

El comando no necesariamente abre una GUI a menos que instale uno. Corriendo git mergetool para mí resultó en vimdiff siendo utilizado. Puede instalar una de las siguientes herramientas para usarlo en su lugar: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

A continuación se muestra el procedimiento de muestra para usar vimdiff para resolver conflictos de fusión. Residencia en este enlace

Paso 1: Ejecuta los siguientes comandos en tu terminal

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

Esto establecerá vimdiff como la herramienta de fusión predeterminada.

Paso 2: Ejecuta el siguiente comando en la terminal

git mergetool

Paso 3: Verá una pantalla vimdiff en el siguiente formato

  +----------------------+
  |       |      |       |
  |LOCAL  |BASE  |REMOTE |
  |       |      |       |
  +----------------------+
  |      MERGED          |
  |                      |
  +----------------------+

Estas 4 vistas son

LOCAL - este es archivo de la rama actual

BASE: antecesor común, cómo se veía el archivo antes de ambos cambios

REMOTO - archivo que se está fusionando con su sucursal

FUSIÓN - fusionar resultado, esto es lo que se guarda en el repositorio

Puede navegar entre estas vistas usando ctrl+w. Puede alcanzar directamente la vista MERGED usando ctrl+w seguido por j.

Más información acerca de la navegación de vimdiff aquí y aquí

Etapa 4. Puede editar la vista Fusionada de la siguiente manera

Si desea obtener cambios de REMOTO

:diffg RE  

Si quieres obtener cambios de BASE

:diffg BA  

Si desea obtener cambios de LOCAL

:diffg LO 

Paso 5. Guardar, Salir, Comprometerse y Limpiar

:wqa guardar y salir de vi

git commit -m "message"

git clean Elimine los archivos adicionales (por ejemplo, * .orig) creados por la herramienta diff.


2415
2017-10-02 17:50



Aquí hay un caso de uso probable, desde la parte superior:

Vas a hacer algunos cambios, pero ¡Ups !, no estás actualizado:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Así que te actualizas e intentas de nuevo, pero tienes un conflicto:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

Entonces decides echar un vistazo a los cambios:

git mergetool

Oh, yo, oh mi, upstream cambió algunas cosas, pero solo para usar mis cambios ... no ... sus cambios ...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

Y luego probamos por última vez

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!


1607
2017-08-04 17:04



Encuentro que las herramientas de combinación rara vez me ayudan a entender el conflicto o la resolución. Por lo general, soy más exitoso mirando los marcadores de conflicto en un editor de texto y usando git log como complemento.

Aquí hay algunos consejos:

Consejo uno

Lo mejor que he encontrado es usar el estilo de conflicto de combinación "diff3":

git config merge.conflictstyle diff3

Esto produce marcadores de conflicto como este:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

La sección del medio es lo que parecía el ancestro común. Esto es útil porque puede compararlo con las versiones superior e inferior para tener una mejor idea de lo que se cambió en cada rama, lo que le da una mejor idea de cuál fue el propósito de cada cambio.

Si el conflicto es solo de unas pocas líneas, esto generalmente hace que el conflicto sea muy obvio. (Saber cómo solucionar un conflicto es muy diferente, debes ser consciente de lo que otras personas están trabajando. Si estás confundido, es mejor simplemente llamar a esa persona a tu habitación para que puedan ver lo que buscas a.)

Si el conflicto es más prolongado, cortaré y pegaré cada una de las tres secciones en tres archivos separados, como "mío", "común" y "de ellos".

Luego puedo ejecutar los siguientes comandos para ver los dos trozos de diff que causaron el conflicto:

diff common mine
diff common theirs

Esto no es lo mismo que usar una herramienta de fusión, ya que una herramienta de fusión también incluirá todos los trozos de diff no conflictivos. Encuentro eso ser una distracción.

Consejo dos

Alguien ya lo mencionó, pero comprender la intención detrás de cada obstáculo generalmente es muy útil para entender de dónde vino un conflicto y cómo manejarlo.

git log --merge -p <name of file>

Esto muestra todas las confirmaciones que tocaron ese archivo entre el ancestro común y las dos cabezas que está fusionando. (Por lo tanto, no incluye las confirmaciones que ya existen en ambas ramas antes de la fusión). Esto le ayuda a ignorar los obstáculos que claramente no son un factor en su conflicto actual.

Consejo tres

Verifique sus cambios con herramientas automáticas.

Si tiene pruebas automatizadas, ejecútelas. Si tienes un hilasejecuta eso Si se trata de un proyecto editable, compárelo antes de comprometerse, etc. En todos los casos, debe realizar algunas pruebas para asegurarse de que los cambios no hayan roto nada. (Diablos, incluso una fusión sin conflictos puede romper el código de trabajo).

Consejo cuatro

Planea por adelantado; comunicarse con compañeros de trabajo.

Planificar con anticipación y estar al tanto de lo que otros están trabajando puede ayudar a prevenir conflictos de fusión y / o ayudar a resolverlos antes, mientras que los detalles aún están frescos.

Por ejemplo, si sabe que usted y otra persona están trabajando en una refacturación diferente que afectará al mismo conjunto de archivos, debe hablarse entre sí antes de tiempo y tener una mejor idea de qué tipo de cambios es cada uno de ustedes. fabricación. Puede ahorrar un tiempo y esfuerzo considerables si realiza los cambios planificados en serie en lugar de hacerlo en paralelo.

Para refactorizaciones importantes que atraviesan una gran franja de código, debe considerar seriamente trabajar en serie: todos dejan de trabajar en esa área del código mientras una persona realiza la refactorización completa.

Si no puede trabajar en serie (debido a la presión del tiempo, tal vez), la comunicación sobre los conflictos de fusión esperados al menos le ayuda a resolver los problemas más pronto, mientras que los detalles aún están frescos. Por ejemplo, si un compañero de trabajo está realizando una serie disruptiva de confirmaciones en el transcurso de un período de una semana, puede optar por fusionar / volver a establecer la base en esa rama de compañeros de trabajo una o dos veces al día durante esa semana. De esta forma, si encuentra conflictos de fusión / rebase, puede resolverlos más rápidamente que si espera unas pocas semanas para fusionar todo en un solo gran bulto.

Consejo cinco

Si no está seguro de una fusión, no la fuerce.

La fusión puede ser abrumadora, especialmente cuando hay muchos archivos en conflicto y los marcadores de conflicto cubren cientos de líneas. Muchas veces, al estimar proyectos de software, no incluimos el tiempo suficiente para elementos generales como manejar una fusión irregular, por lo que se siente como un lastre para pasar varias horas diseccionando cada conflicto.

A largo plazo, planear con anticipación y estar al tanto de lo que otros están trabajando son las mejores herramientas para anticipar conflictos de fusión y prepararse para resolverlos correctamente en menos tiempo.


683
2017-09-28 21:08



  1. Identifica qué archivos están en conflicto (Git debería decirte esto).

  2. Abra cada archivo y examine los diffs; Git los demarca. Con suerte, será obvio qué versión de cada bloque conservar. Es posible que deba discutirlo con otros desarrolladores que hayan cometido el código.

  3. Una vez que haya resuelto el conflicto en un archivo git add the_file.

  4. Una vez que hayas resuelto todas conflictos, hacer git rebase --continue o cualquier comando Git dijo que hicieras cuando completaste.


321
2017-10-02 12:41



Mira las respuestas en la pregunta de desbordamiento de pila Abortar una fusión en Git, especialmente La respuesta de Charles Bailey que muestra cómo ver las diferentes versiones del archivo con problemas, por ejemplo,

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

97
2017-10-03 15:15



Los conflictos de combinación ocurren cuando se realizan cambios en un archivo al mismo tiempo. Aquí está cómo resolverlo.

git CLI

Aquí hay pasos simples que hacer cuando entra en estado conflictivo:

  1. Tenga en cuenta la lista de archivos en conflicto con: git status (debajo Unmerged paths sección).
  2. Resuelva los conflictos por separado para cada archivo mediante uno de los siguientes enfoques:

    • Use GUI para resolver los conflictos: git mergetool (la forma más fácil).

    • Para aceptar versiones remotas / otras, use: git checkout --theirs path/file. Esto rechazará cualquier cambio local que haya hecho para ese archivo.

    • Para aceptar local / nuestra versión, use: git checkout --ours path/file

      Sin embargo, debe tener cuidado, ya que los cambios remotos hacen que los conflictos se hagan por alguna razón.

      Relacionado: ¿Cuál es el significado preciso de "nuestro" y "de ellos" en git?

    • Edite los archivos en conflicto manualmente y busque el bloque de código entre <<<<</>>>>> luego elige la versión ya sea desde arriba o desde abajo =====. Ver: Cómo se presentan los conflictos.

    • Los conflictos de ruta y nombre de archivo pueden ser resueltos por git add/git rm.

  3. Finalmente, revise los archivos listos para el commit usando: git status.

    Si aún tiene archivos debajo Unmerged paths, y resolviste el conflicto manualmente, luego hazle saber a Git que lo resolviste de la siguiente manera: git add path/file.

  4. Si todos los conflictos se resolvieron con éxito, realice los cambios de la siguiente manera: git commit -a y empujar al control remoto como de costumbre.

Ver también: Resolviendo un conflicto de fusión desde la línea de comando en GitHub

DiffMerge

He usado con éxito DiffMerge que puede comparar visualmente y fusionar archivos en Windows, macOS y Linux / Unix.

Gráficamente puede mostrar los cambios entre 3 archivos y permite la fusión automática (cuando es seguro hacerlo) y un control total sobre la edición del archivo resultante.

DiffMerge

Fuente de imagen: DiffMerge (Captura de pantalla de Linux)

Simplemente descárguelo y ejecute en repos como:

git mergetool -t diffmerge .

Mac OS

En macOS puedes instalarlo a través de:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

Y probablemente (si no se proporciona) necesita el siguiente contenedor extra simple colocado en su RUTA (p. /usr/bin)

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Luego puede usar los siguientes atajos de teclado:

  • -Alt-Arriba/Abajo para saltar a los cambios anteriores / siguientes.
  • -Alt-Izquierda/Derecha aceptar cambios de izquierda a derecha

Alternativamente puedes usar opendiff (parte de Xcode Tools) que le permite combinar dos archivos o directorios para crear un tercer archivo o directorio.


88
2017-08-05 14:29



Si realiza confirmaciones pequeñas frecuentes, comience por mirar los comentarios de compromiso con git log --merge. Entonces git diff te mostrará los conflictos.

Para conflictos que involucran más de unas líneas, es más fácil ver lo que está sucediendo en una herramienta de GUI externa. Me gusta opendiff: Git también admite vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, emerge de la caja y puedes instalar otros: git config merge.tool "your.tool" configurará su herramienta elegida y luego git mergetool después de una fusión fallida le mostrará las diferencias en el contexto.

Cada vez que edite un archivo para resolver un conflicto, git add filename actualizará el índice y su diff ya no lo mostrará. Cuando se manejan todos los conflictos y se han procesado sus archivos git add-ed, git commit completará su fusión.


73
2017-10-02 16:11



Ver Cómo se presentan los conflictos o, en Git, el git merge documentación para comprender qué son los marcadores de conflicto de fusión.

También el Cómo resolver conflictos la sección explica cómo resolver los conflictos:

Después de ver un conflicto, puedes hacer dos cosas:

  • Decide no fusionar. Las únicas limpiezas que necesita son restablecer el archivo de índice al HEAD comprometerse a invertir 2. y limpiar los cambios del árbol de trabajo hechos por 2. y 3 .; git merge --abort se puede usar para esto

  • Resuelve los conflictos. Git marcará los conflictos en el árbol de trabajo. Edite los archivos en forma y git add ellos al índice. Utilizar git commit para sellar el trato.

Puede solucionar el conflicto con una serie de herramientas:

  • Usa una herramienta de combinación. git mergetool para lanzar un mergetool gráfico que te ayudará a pasar por la fusión.

  • Mira los diffs. git diff mostrará una diferencia de tres vías, destacando los cambios de ambos HEAD y MERGE_HEAD versiones.

  • Mire los diffs de cada rama. git log --merge -p <path> mostrará diffs primero para el HEAD versión y luego el MERGE_HEAD versión.

  • Mira los originales. git show :1:filename muestra el ancestro común, git show :2:filename muestra el HEAD versión, y git show :3:filename muestra el MERGE_HEAD versión.

También puede leer sobre fusionar marcadores de conflicto y cómo resolverlos en el Pro Git sección de libro Conflictos básicos de fusión.


43
2017-07-14 18:34



por Emacs usuarios que desean resolver conflictos de combinación de forma semi-manual:

git diff --name-status --diff-filter=U

muestra todos los archivos que requieren resolución de conflicto.

Abra cada uno de esos archivos uno por uno, o todos a la vez por:

emacs $(git diff --name-only --diff-filter=U)

Al visitar un búfer que requiera ediciones en Emacs, escriba

ALT+x vc-resolve-conflicts

Esto abrirá tres búferes (el mío, el suyo y el búfer de salida). Navegue presionando 'n' (siguiente región), 'p' (región de previsión). Presione 'a' y 'b' para copiar la mina o su región en el búfer de salida, respectivamente. Y / o edite el buffer de salida directamente.

Cuando termine: presione 'q'. Emacs le pregunta si desea guardar este búfer: sí. Después de finalizar un buffer, márquelo como resuelto al ejecutar desde el teriminal:

git add FILENAME

Cuando haya terminado con todos los buffers, escriba

git commit

para terminar la fusión


36
2018-02-22 23:04



Siga los siguientes pasos para solucionar los conflictos de fusión en Git:

  1. Verifica el estado de Git: estado de git

  2. Obtener el parche: git fetch (selecciona el parche correcto de tu commit de Git)

  3. Verifique una sucursal local (temp1 en mi ejemplo aquí): git checkout -b temp1

  4. Extraiga los contenidos recientes de master: git pull --rebase origen master

  5. Inicie el mergetool, compruebe los conflictos y corríjalos ... y compruebe los cambios en la rama remota con su rama actual: git mergetool

  6. Verifique el estado nuevamente:   estado de git

  7. Elimine los archivos no deseados creados localmente por mergetool, generalmente mergetool crea archivos adicionales con la extensión * .orig. Elimine ese archivo, ya que es solo el duplicado y corrija los cambios de forma local y agregue la versión correcta de sus archivos. git add #your_changed_correct_files

  8. Verifique el estado nuevamente: estado de git

  9. Confirme los cambios en la misma identificación de confirmación (esto evita un nuevo conjunto de parches separado): git commit - enmienda

  10. Empujar a la rama principal: git push (a su repositorio de Git)


28
2018-04-16 07:02