Cómo resolver conflictos de fusión en Git


4769

¿Cómo resuelvo los conflictos de fusión en Git?


31
La siguiente publicación de blog parece dar un muy buen ejemplo sobre cómo manejar el conflicto de fusión con Git que debería llevarlo en la dirección correcta. Manejando y evitando conflictos en Git
mwilliams

44
Puede configurar una herramienta de combinación (kdiff3 jebaird.com/2013/07/08/… ) y luego usar git mergetool. Cuando trabajas en grandes equipos de desarrolladores, siempre encontrarás conflictos de fusión.
Grady G Cooper

¡No olvide que puede mitigar la mayoría de los conflictos de fusión fusionando regularmente aguas abajo!
Ant P


8
Pregunta fascinante: cuando se le preguntó en 2008, 100% abierto terminó sin ninguna pista sobre de qué se trata realmente (¿se trata de GUI? ¿Acerca de los comandos git? ¿Sobre la semántica? 30 respuestas, todas ellas (por lo que muestra un vistazo rápido) más o menos sobre diferentes herramientas diff3 y merge, ninguna aceptada. La respuesta más votada menciona un comando que ni siquiera funciona con una gitinstalación predeterminada . Logré llegar a la página de inicio de SE para mí hoy, 2017, con 1.3 millones de visitas y miles de votos en ambos sentidos. Fascinante.
AnoE

Respuestas:


2913

Tratar: git mergetool

Abre una GUI que lo guía a través de cada conflicto, y puede elegir cómo fusionar. A veces requiere un poco de edición manual después, pero generalmente es suficiente por sí solo. Es mucho mejor que hacer todo a mano, sin duda.

Según el comentario de @JoshGlover:

El comando

no necesariamente abre una GUI a menos que instales una. Correr git mergetoolpor mí resultó en vimdiffser utilizado. Puede instalar una de las siguientes herramientas para utilizarla en su lugar: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

A continuación se muestra el procedimiento de ejemplo que se utilizará vimdiffpara resolver conflictos de fusión. Basado 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 : Ejecute 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 el archivo de la rama actual

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

REMOTO: archivo que está fusionando en su rama

FUSIONADO: resultado de fusión, esto es lo que se guarda en el repositorio

Puede navegar entre estas vistas usando ctrl+ w. Puede acceder directamente a la vista MERGED usando ctrl+ wseguido de j.

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

Paso 4 . Puede editar la vista FUSIONADA de la siguiente manera

Si desea obtener cambios desde REMOTO

:diffg RE  

Si desea obtener cambios desde BASE

:diffg BA  

Si desea obtener cambios de LOCAL

:diffg LO 

Paso 5 . Guardar, salir, confirmar y limpiar

:wqa guardar y salir de vi

git commit -m "message"

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


54
Para su información, puede usar git mergetool -ypara guardar algunas teclas si combina muchos archivos a la vez.
davr

373
Bueno, no necesariamente abre una GUI a menos que instales una. Correr git mergetoolpor mí resultó en vimdiffser utilizado. Puede instalar una de las siguientes herramientas para utilizarla en su lugar: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge.
Josh Glover

31
Buen punto Josh. En ubuntu he tenido la mejor suerte con meld, su visualización de combinación de tres vías no está mal. En OSX, git eligió un buen valor predeterminado.
Peter Burns

18
Esto abrió KDiff3. Que no tengo ni idea de cómo usarlo.
David Murdoch

77
También puede usar Beyond Compare 3 ahora ( git mergetool -t bc3).
AzP

1703

Aquí hay un caso de uso probable, desde arriba:

Vas a hacer algunos cambios, pero 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 nuevamente, 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 my, oh my, 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 intentamos una última vez

git pull origin master

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

Ta-da!


19
Esto fue súper útil porque tuve muchos errores de fusión con archivos binarios (activos artísticos) y la fusión de ellos parece fallar siempre, así que necesito sobrescribirlo siempre con el nuevo archivo y no "fusionar"
petrocket

188
¡Cuidado! El significado de - nuestros y - sus se invierte. --ours == el control remoto. --theirs == local. Vergit merge --help
mmell

57
En mi caso, confirmo que --theirs = repositorio remoto, --ours = mi propio repositorio local. Es lo opuesto a los comentarios de @mmell.
Aryo

24
@mmell Solo en un rebase, aparentemente. Verthis question
Navin

184
Chicos, "lo nuestro" y "lo suyo" es relativo a si se está fusionando o no. Si se está fusionando , entonces "nuestro" significa la rama en la que se está fusionando, y "la suya" es la rama en la que se está fusionando. Cuando rebase , entonces "nuestro" significa los compromisos en los que se rebase , mientras que "el suyo" se refiere a los commits que desea rehacer.

736

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

Aquí hay algunos consejos:

Consejo uno

Lo mejor que he encontrado es usar el estilo de conflicto de fusió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 central es el aspecto del 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 era el propósito de cada cambio.

Si el conflicto es solo unas pocas líneas, esto generalmente hace que el conflicto sea muy obvio. (Saber cómo solucionar un conflicto es muy diferente; debe saber en qué están trabajando otras personas. Si está confundido, probablemente sea mejor llamar a esa persona a su habitación para que puedan ver lo que está buscando). a.)

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

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 diferencias no conflictivos. Me parece que eso me distrae.

Consejo dos

Alguien ya mencionó esto, pero comprender la intención detrás de cada trozo de diferencia generalmente es muy útil para comprender 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 fusionarse). Esto le ayuda a ignorar las diferencias que claramente no son un factor en su conflicto actual.

Consejo tres

Verifique sus cambios con herramientas automatizadas.

Si tiene pruebas automatizadas, ejecútelas. Si tienes una pelusa , corre eso. Si se trata de un proyecto armable, compílelo antes de comprometerse, etc. En todos los casos, debe hacer un poco de prueba para asegurarse de que sus cambios no rompan nada. (Diablos, incluso una fusión sin conflictos puede romper el código de trabajo).

Consejo cuatro

Planificar con anticipación; comunicarse con compañeros de trabajo.

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

Por ejemplo, si sabe que usted y otra persona están trabajando en una refactorización diferente que afectará el mismo conjunto de archivos, deben hablar entre ellos con anticipación y tener una mejor idea de qué tipo de cambios es cada uno de ustedes haciendo. Puede ahorrar tiempo y esfuerzo considerables si realiza los cambios planificados en serie en lugar de en paralelo.

Para refactorizaciones importantes que atraviesan una gran franja de código, debe considerar 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 (tal vez debido a la presión del tiempo, tal vez), comunicarse sobre los conflictos de fusión esperados al menos lo ayuda a resolver los problemas antes mientras los detalles aún están frescos. Por ejemplo, si un compañero de trabajo está haciendo una serie de compromisos disruptivos en el transcurso de un período de una semana, puede optar por fusionar / rebase en esa rama de compañeros de trabajo una o dos veces al día durante esa semana. De esa manera, si encuentra conflictos de fusión / rebase, puede resolverlos más rápidamente que si espera unas semanas para fusionar todo en un gran bulto.

Consejo cinco

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

La fusión puede parecer 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 suficiente tiempo para elementos generales como manejar una fusión retorcida, por lo que se siente como un verdadero lastre pasar varias horas diseccionando cada conflicto.

A la larga, planificar 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.


66
La opción diff3 es una gran característica para tener con fusiones. La única GUI que he encontrado que muestra que es de Perforce p4merge, que se puede instalar y usar por separado de otras herramientas de Perforce (que no he usado, pero escuché quejas).
alxndr

3
Después de un intento de rebase que resultó en un conflicto de fusión: $ git log --merge -p build.xml output: fatal: --merge sin MERGE_HEAD?
Ed Randall

¿Qué pasa si tengo cambios en un archivo de branch1 y la eliminación de ese archivo en branch2? ¿Cómo puedo resolver ese conflicto de fusión? ¿Hay alguna forma de usar git donde pueda fusionarlos manteniendo los cambios de una rama?
Miel el

git config merge.conflictstyle diff3- gracias Señor. Esto es increíble y me ha liberado de intentar encontrar (y pagar $$) una buena GUI de combinación de 3 vías. OMI, esto es mejor porque muestra el ancestro común, así como local / remoto, y muestra las últimas líneas de registro de confirmación que (AFAIK) no hace GUI. Las confirmaciones definitivamente lo ayudan a identificar qué código pertenece a qué rama.
ffxsam

He descubierto que, a veces, el estilo de conflicto diff3 da como resultado enormes trozos de diferencias que son en gran medida idénticos, mientras que el valor predeterminado producirá trozos más pequeños y manejables. Desafortunadamente, no tengo un reproductor que pueda usar para un informe de error. Pero si encuentra este problema, puede considerar desactivar la opción temporalmente.
Dave Abrahams

348
  1. Identifique qué archivos están en conflicto (Git debería decirle esto).

  2. Abra cada archivo y examine las diferencias; Git los demarca. Con suerte, será obvio qué versión de cada bloque mantener. Es posible que deba analizarlo 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 todos los conflictos, haz git rebase --continueo cualquier comando que Git dijo que hicieras cuando lo completaras.


38
@Justin Piense en Git como seguimiento de contenido en lugar de archivos de seguimiento. Entonces es fácil ver que el contenido que ha actualizado no está en el repositorio y debe agregarse. Esta forma de pensar también explica por qué Git no rastrea las carpetas vacías: aunque técnicamente son archivos, no hay ningún contenido para rastrear.
Gareth

77
el contenido está ahí, el conflicto ocurre porque hay 2 versiones de contenido. Por lo tanto, "git add" no suena correcto. Y no funciona (git add, git commit) si desea confirmar solo ese archivo después de que se resuelva el conflicto ("fatal: no se puede realizar una confirmación parcial durante una fusión")
Dainius

1
Sí, técnicamente, esto responde a la pregunta que se hizo, pero no es una respuesta utilizable, en mi opinión, lo siento. ¿De qué sirve hacer que una rama sea igual a otra? Por supuesto, una fusión tendrá conflictos ..
Thufir

55
Thulfir: ¿quién dijo algo sobre hacer que una rama sea igual a otra? Existen diferentes escenarios en los que debe fusionarse, sin "hacer que una rama sea igual a otra". Una es cuando haya terminado con una rama de desarrollo y desee incorporar sus cambios en la rama maestra; después de esto, la rama de desarrollo se puede eliminar. Otra es cuando desea cambiar la base de su rama de desarrollo, para facilitar la fusión final final en el maestro.
Teemu Leisti

44
@JustinGrant coloca los git addarchivos en el índice; sí no añade nada al repositorio. git commitagrega cosas al repositorio. Este uso tiene sentido para las fusiones: la fusión automáticamente organiza todos los cambios que se pueden fusionar automáticamente; es su responsabilidad fusionar el resto de los cambios y agregarlos al índice cuando haya terminado.
Mark E. Haase

105

Consulte 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

También revise la opción "-m" para "git checkout -m" - le permite extraer las diferentes moscas de vuelta a su espacio de trabajo
qneill

Esto me salvó. Mirar cada archivo por separado me permitió recordar lo que estaba buscando en cada rama. Entonces podría tomar la decisión de elegir.
Rohmer

99

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

git CLI

Aquí hay pasos simples sobre qué hacer cuando entra en estado de conflicto:

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

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

    • Para aceptar a distancia / otra versión, utilice: git checkout --theirs path/file. Esto rechazará cualquier cambio local que haya realizado 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 que los conflictos se hicieron por alguna razón.

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

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

    • Los conflictos de ruta y nombre de archivo se pueden resolver con git add/ git rm.

  3. Por último, revise los archivos listos para cometer usando: git status.

    Si todavía tiene alguna archivos bajo Unmerged paths, y se ha solucionado el conflicto de forma manual, a continuación, dejar que Git sabe que lo resolvió por: git add path/file.

  4. Si todos los conflictos se resolvieron con éxito, confirme los cambios de la siguiente manera: git commit -ay presione en remoto como de costumbre.

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

Para obtener un tutorial práctico, consulte: Escenario 5: Corregir conflictos de fusión por Katacoda .

DiffMerge

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

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

DiffMerge

Fuente de la imagen: DiffMerge (captura de pantalla de Linux)

Simplemente descárguelo y ejecútelo como:

git mergetool -t diffmerge .

Mac OS

En macOS puede instalar a través de:

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

Y probablemente (si no se proporciona) necesita el siguiente envoltorio extra simple colocado en su RUTA (por ejemplo /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 métodos abreviados de teclado:

  • - Alt- Up/ Downpara saltar a los cambios anteriores / siguientes.
  • - Alt- Left/ Rightpara aceptar el cambio de izquierda o derecha

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


79

Si está haciendo pequeños commits frecuentes, entonces comience mirando los comentarios de commit con git log --merge. Luego git diffte mostrará los conflictos.

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

Cada vez que edite un archivo para resolver un conflicto, git add filenameactualizará el índice y su diff ya no lo mostrará. Cuando se manejen todos los conflictos y se hayan git addeditado sus archivos , git commitcompletará su fusión.


8
Usar "git add" es el verdadero truco aquí. Es posible que ni siquiera quiera comprometerse (tal vez desee guardar), pero debe hacer "git add" para completar la fusión. Creo que mergetool hace el agregado por usted (aunque no está en la página de manual), pero si lo hace manualmente, debe usar "git add" para completarlo (incluso si no desea comprometerse).
nobar

47

Vea cómo se presentan los conflictos o, en Git, la git mergedocumentación para comprender qué son los marcadores de conflicto de fusión.

Además, la sección Cómo resolver conflictos explica cómo resolver los conflictos:

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

  • Decide no fusionar. Las únicas limpiezas que necesita son restablecer el archivo de índice a la HEADconfirmación para invertir 2. y limpiar los cambios en el árbol de trabajo realizados por 2. y 3 .; git merge --abortse puede usar para esto

  • Resolver los conflictos. Git marcará los conflictos en el árbol de trabajo. Edite los archivos en forma y git adden el índice. Use git commitpara sellar el trato.

Puede resolver el conflicto con una serie de herramientas:

  • Usa una herramienta de combinación. git mergetoolpara iniciar una herramienta de combinación gráfica que lo ayudará a completar la combinación.

  • Mira las diferencias. git diffmostrará un diferencial de tres vías, resaltando los cambios de las versiones HEADy MERGE_HEAD.

  • Mira las diferencias de cada rama. git log --merge -p <path>mostrará diffs primero para la HEADversión y luego la MERGE_HEADversión.

  • Mira los originales. git show :1:filenamemuestra el ancestro común, git show :2:filenamemuestra la HEADversión y git show :3:filenamemuestra la MERGE_HEADversión.

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


42

Quiero mi o su versión completa, o quiero revisar los cambios individuales y decidir por cada uno de ellos.

Acepte completamente mi versión o la de ellos :

Aceptar mi versión (local, nuestra):

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

Acepte su versión (remota, suya):

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

Si desea hacer para todos los archivos de conflicto ejecute:

git merge --strategy-option ours

o

git merge --strategy-option theirs

Revise todos los cambios y acéptelos individualmente

  1. git mergetool
  2. Revise los cambios y acepte cualquier versión para cada uno de ellos.
  3. git add <filename>
  4. git commit -m "merged bla bla"

El valor predeterminado mergetoolfunciona en la línea de comandos . Cómo usar una línea de comando mergetool debería ser una pregunta separada.

También puede instalar una herramienta visual para esto, por ejemplo, meldy ejecutar

git mergetool -t meld

Abrirá la versión local (la nuestra), la versión "base" o "fusionada" (el resultado actual de la fusión) y la versión remota (la suya). Guarde la versión fusionada cuando haya terminado, git mergetool -t meldvuelva a ejecutarla hasta que aparezca "No es necesario fusionar archivos", luego vaya a los Pasos 3. y 4.


Este comando: git checkout --theirs - <nombre de archivo> cambió TODOS los archivos a los suyos, no solo <nombre de archivo>
Donato

En realidad estaba equivocado. Esto solo actualiza el archivo especificado.
Donato

40

Para usuarios de Emacs que desean resolver conflictos de fusión de forma semi-manual:

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

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

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

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

Cuando visite un búfer que requiera modificaciones en Emacs, escriba

ALT+x vc-resolve-conflicts

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

Cuando termine: presione 'q'. Emacs le pregunta si desea guardar este búfer: sí. Después de terminar un búfer, márquelo como resuelto ejecutando desde el penal:

git add FILENAME

Cuando termine con todos los tipos de tampones

git commit

para terminar la fusión


33

Prima:

Al hablar de pull / fetch / merge en las respuestas anteriores, me gustaría compartir un truco interesante y productivo,

git pull --rebase

Este comando anterior es el comando más útil en mi vida git que ahorró mucho tiempo.

Antes de enviar su cambio recién confirmado al servidor remoto, intente git pull --rebasemás bien con el git pullmanual mergey sincronizará automáticamente los últimos cambios del servidor remoto (con una búsqueda + fusión) y colocará su último compromiso local en la parte superior del registro git. No necesita preocuparse por la extracción / fusión manual.

En caso de conflicto, solo use

git mergetool
git add conflict_file
git rebase --continue

Encuentre detalles en: http://gitolite.com/git-pull--rebase


32

Simplemente, si sabe bien que los cambios en uno de los repositorios no son importantes, y desea resolver todos los cambios a favor del otro, use:

git checkout . --ours

para resolver cambios a favor de su repositorio , o

git checkout . --theirs

para resolver cambios a favor del otro o del repositorio principal .

O bien, tendrá que usar una herramienta de combinación de GUI para recorrer los archivos uno por uno, digamos que es la herramienta de combinación p4mergeo escribir el nombre de cualquiera que ya haya instalado

git mergetool -t p4merge

y después de terminar un archivo, tendrá que guardar y cerrar, para que se abra el siguiente.


2
Git Checkout. - resuelven mi problema gracias
Ramesh Chand

si prefiere resolver conflictos manualmente, intente abrir la carpeta en Visual Studio Code, marca archivos con conflictos y líneas de conflicto de colores dentro de cada uno
Mohamed Selim

31

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

  1. Verifique el estado de Git: estado de git

  2. Obtenga el conjunto de parches: git fetch (consulte el parche correcto de su confirmación de Git)

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

  4. Extraiga los contenidos recientes del maestro: git pull --rebase origin master

  5. Inicie mergetool y verifique los conflictos y corríjalos ... y verifique 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 un archivo adicional con la extensión * .orig. Elimine ese archivo ya que es solo el duplicado y arregle los cambios localmente 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 ID de confirmación (esto evita un nuevo conjunto de parches por separado): git commit --amend

  10. Empuje a la rama maestra: git push (a su repositorio de Git)


28

Hay 3 pasos:

  1. Encuentra qué archivos causan conflictos por comando

    git status
    
  2. Verifique los archivos, en los que encontrará los conflictos marcados como

    <<<<<<<<head
    blablabla
    
  3. Cámbielo a la forma que desee, luego confirme con comandos

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

¡Trabajó para mi! ¡Gracias!
Nuwan Jayawardene

Debe prestar atención si hace esto durante el rebase. Deberías usar git rebase --continuar en lugar de git commit
Samuel Dauzon

27

Puede solucionar conflictos de fusión de varias maneras, como otros han detallado.

Creo que la clave real es saber cómo fluyen los cambios con los repositorios locales y remotos. La clave para esto es comprender las ramas de seguimiento. He descubierto que pienso en la rama de seguimiento como la 'pieza faltante en el medio' entre mi directorio local de archivos reales y el control remoto definido como origen.

Personalmente me he acostumbrado a 2 cosas para ayudar a evitar esto.

En vez de:

git add .
git commit -m"some msg"

Que tiene dos inconvenientes:

a) Todos los archivos nuevos / modificados se agregan y eso puede incluir algunos cambios no deseados.
b) No puede revisar primero la lista de archivos.

Entonces, en cambio, hago:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

De esta manera, usted es más deliberado acerca de qué archivos se agregan y también puede revisar la lista y pensar un poco más mientras usa el editor para el mensaje. Creo que también mejora mis mensajes de confirmación cuando uso un editor de pantalla completa en lugar de la -mopción.

[Actualización: a medida que pasó el tiempo, cambié más a:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

Además (y más relevante para su situación), trato de evitar:

git pull

o

git pull origin master.

porque pull implica una fusión y si tiene cambios locales que no desea fusionar, puede terminar fácilmente con el código fusionado y / o fusionar conflictos para el código que no debería haberse fusionado.

En cambio trato de hacer

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

También puede encontrar esto útil:

git branch, fork, fetch, merge, rebase y clone, ¿cuáles son las diferencias?


Oye, entendí un poco tu respuesta. Pero como soy nuevo en los conflictos de fusión de github, creo que falta algo. ¿Qué ocurre con sus modificaciones locales cuando lo hace git checkout mastery git fetch e git rebase --hard origin/master
Suhaib

Creo que deberías agregar más detalles sobre qué hacer. Otro ejemplo que me confunde, usted mencionó en su respuesta: lo hacemos git add ., ¿guardará nuestras modificaciones locales para que podamos seguir git checkout master? o son dos escenarios diferentes?
Suhaib

@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option uso duro: git rebase [-i] [opciones] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] o: git rebase [-i] [ opciones] [--exec <cmd>] [--onto <newbase>] --root [<branch>] o: git rebase --continue | --abort | --skip | --edit-todo `
likejudo

24

La respuesta de CoolAJ86 resume casi todo. En caso de que haya cambios en ambas ramas en el mismo código, deberá realizar una fusión manual. Abra el archivo en conflicto en cualquier editor de texto y debería ver la siguiente estructura.

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

Elija una de las alternativas o una combinación de ambas de la manera que desee que sea el nuevo código, mientras elimina signos de igual y corchetes angulares.

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

Parece que no siempre funciona para mí y generalmente termina mostrando cada confirmación que era diferente entre las dos ramas, esto sucede incluso cuando se usa --para separar la ruta del comando.

Lo que hago para solucionar este problema es abrir dos líneas de comando y en una ejecución

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

y en el otro

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

Reemplazando $MERGED_IN_BRANCHcon la rama en la que me fusioné y [path]con el archivo que está en conflicto. Este comando registrará todas las confirmaciones, en forma de parche, entre ( ..) dos confirmaciones. Si deja un lado vacío como en los comandos anteriores, git usará automáticamente HEAD(la rama en la que se está fusionando en este caso).

Esto le permitirá ver qué confirmaciones ingresaron al archivo en las dos ramas después de que divergieron. Por lo general, hace que sea mucho más fácil resolver conflictos.


16

Utilizando patience

Me sorprende que nadie más haya hablado de resolver conflictos utilizando patiencela estrategia recursiva de fusión. Para un gran conflicto de fusión, el uso me patienceproporcionó buenos resultados. La idea es que intente hacer coincidir bloques en lugar de líneas individuales.

Si cambia la sangría de su programa, por ejemplo, la estrategia de fusión Git predeterminada a veces coincide con llaves simples {que pertenecen a diferentes funciones. Esto se evita con patience:

git merge -s recursive -X patience other-branch

De la documentación:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

Comparación con el ancestro común

Si tiene un conflicto de fusión y quiere ver lo que otros tenían en mente al modificar su rama, a veces es más fácil comparar su rama directamente con el antepasado común (en lugar de nuestra rama). Para eso puedes usar merge-base:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

Por lo general, solo desea ver los cambios para un archivo en particular:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

En mi caso, esto no resolvió bien los conflictos de fusión, ya que por alguna razón mantuvo líneas duplicadas de configuración en proyectos de C #. Aunque fue más amigable que TODO EL ARCHIVO ES DIFERENTE, lo que tenía antes
Mathijs Segers

15

A partir del 12 de diciembre de 2016, puede fusionar sucursales y resolver conflictos en github.com

Por lo tanto, si no desea utilizar la línea de comandos o las herramientas de terceros que se ofrecen aquí desde respuestas anteriores , vaya con la herramienta nativa de GitHub.

Esta publicación de blog explica en detalle, pero lo básico es que al 'fusionar' dos ramas a través de la interfaz de usuario, ahora verá una opción de 'resolver conflictos' que lo llevará a un editor que le permitirá lidiar con estos conflictos de fusión.

ingrese la descripción de la imagen aquí


no se trata de github, por lo que rechacé lo que considero una respuesta muy pobre.
mschuett

1
@mschuett tiene razón, la pregunta es "cómo resolver conflictos en git", no "cómo resolver conflictos en github". Hay una diferencia y ya hay demasiadas personas que piensan que git y github son lo mismo, por lo que cualquier cosa que propague ese sentimiento está mal.
Patrick Mevzek

15

Si desea fusionar de rama (prueba) a maestra, puede seguir estos pasos:

Paso 1 : ve a la sucursal

git checkout test

Paso 2 :

git pull --rebase origin master

Paso 3 : Si hay algunos conflictos, vaya a estos archivos para modificarlo.

Paso 4 : agrega estos cambios

git add #your_changes_files

Paso 5 :

git rebase --continue

Paso 6 : Si todavía hay conflicto, vuelva al paso 3 nuevamente. Si no hay conflicto, haga lo siguiente:

git push origin +test

Paso 7 : Y luego no hay conflicto entre prueba y maestro. Puede usar fusionar directamente.


13

Siempre sigo los pasos a continuación para evitar conflictos.

  • git checkout master (Ven a la rama maestra)
  • git pull (Actualice su maestro para obtener el último código)
  • git checkout -b mybranch (Revisa una nueva rama y comienza a trabajar en esa rama para que tu maestro siempre permanezca en la parte superior del tronco).
  • git add. AND git commit AND git push (en su sucursal local después de sus cambios)
  • git checkout master (Vuelve con tu maestro)

Ahora puede hacer lo mismo y mantener todas las sucursales locales que desee y trabajar simultáneamente, simplemente haciendo un pago de git a su sucursal cuando sea necesario.


12

Los conflictos de fusión pueden ocurrir en diferentes situaciones:

  • Al ejecutar "git fetch" y luego "git merge"
  • Al ejecutar "git fetch" y luego "git rebase"
  • Al ejecutar "git pull" (que en realidad es igual a una de las condiciones mencionadas anteriormente)
  • Cuando se ejecuta "git stash pop"
  • Cuando aplica parches git (confirmaciones que se exportan a archivos para transferir, por ejemplo, por correo electrónico)

Debe instalar una herramienta de combinación que sea compatible con Git para resolver los conflictos. Personalmente uso KDiff3, y lo he encontrado agradable y útil. Puede descargar su versión de Windows aquí:

https://sourceforge.net/projects/kdiff3/files/

Por cierto, si instala Git Extensions, hay una opción en su asistente de configuración para instalar Kdiff3.

Luego configure git configs para usar Kdiff como su herramienta de combinación:

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(Recuerde reemplazar la ruta con la ruta real del archivo exe Kdiff).

Luego, cada vez que encuentre un conflicto de fusión, solo necesita ejecutar este comando:

$git mergetool

Luego abre el Kdiff3, y primero intenta resolver los conflictos de fusión automáticamente. La mayoría de los conflictos se resolverían de forma espontánea y debe solucionar el resto manualmente.

Así es como se ve Kdiff3:

Ingrese la descripción de la imagen aquí

Luego, una vez que haya terminado, guarde el archivo y pasará al siguiente archivo con conflicto y volverá a hacer lo mismo hasta que se resuelvan todos los conflictos.

Para verificar si todo se fusionó con éxito, simplemente ejecute el comando mergetool nuevamente, debe obtener este resultado:

$git mergetool
No files need merging

8

Esta respuesta es agregar una alternativa para los usuarios de VIM como I que prefiere hacer todo dentro del editor.


TL; DR

ingrese la descripción de la imagen aquí


A Tpope se le ocurrió este gran complemento para VIM llamado fugitivo . Una vez instalado, puede ejecutar :Gstatuspara verificar los archivos que tienen conflictos y :Gdiffabrir Git de una manera combinada.

Una vez en la fusión de 3 vías, fugitivo le permitirá obtener los cambios de cualquiera de las ramas que está fusionando de la siguiente manera:

  • :diffget //2, obtenga cambios de la rama original ( HEAD ):
  • :diffget //3, obtenga cambios de la rama de fusión:

Una vez que haya terminado de fusionar el archivo, escriba :Gwriteel búfer fusionado. Vimcasts lanzó un gran video que explica en detalle estos pasos.


6

Gitlense para el código VS

Puede probar Gitlense para VS Code, sus características principales son:

3. Resuelva fácilmente los conflictos.

Ya me gusta esta característica:

ingrese la descripción de la imagen aquí

2. Línea actual culpable.

ingrese la descripción de la imagen aquí

3. Culpa de canalones

ingrese la descripción de la imagen aquí

4. Culpa de la barra de estado

ingrese la descripción de la imagen aquí

Y hay muchas características que puedes consultar aquí .


5

git fetch
git checkout tu rama
git rebase master

En este paso, intentará solucionar el conflicto utilizando su IDE preferido

Puede seguir este enlace para verificar cómo solucionar el conflicto en el archivo
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

git add
git rebase --continue
git commit --amend
git push origin HEAD: refs / drafts / master (push like a drafts)

Ahora todo está bien y encontrarás tu compromiso en gerrit

Espero que esto ayude a todos en relación con este tema.


3

Pruebe Visual Studio Code para editar si aún no lo ha hecho. Lo que hace es después de intentar fusionar (y aterrizar en conflictos de fusión). El código VS detecta automáticamente los conflictos de fusión.

Puede ayudarlo muy bien al mostrar cuáles son los cambios realizados en el original y si acepta incomingo

current change(que significa original antes de fusionarse)?

¡Me ayudó y también puede funcionar para ti!

PD: funcionará solo si ha configurado git con su código y Visual Studio Code.


2

Una forma más segura de resolver conflictos es usar git-mediate (las soluciones comunes sugeridas aquí son bastante propensas a errores).

Vea esta publicación para una introducción rápida sobre cómo usarla.


2

Para aquellos que usan Visual Studio (2015 en mi caso)

  1. Cierra tu proyecto en VS. Especialmente en grandes proyectos, VS tiende a enloquecer cuando se combina con la interfaz de usuario.

  2. Haga la fusión en el símbolo del sistema.

    git checkout target_branch

    git merge source_branch

  3. Luego abra el proyecto en VS y vaya a Team Explorer -> Branch. Ahora hay un mensaje que dice que Merge está pendiente y los archivos en conflicto se enumeran justo debajo del mensaje.

  4. Haga clic en el archivo en conflicto y tendrá la opción de Fusionar, Comparar, Tomar origen, Tomar destino. La herramienta de combinación en VS es muy fácil de usar.


Estoy usando VS Code 2017 en un proyecto muy grande y no tengo necesidad de cerrar el proyecto. Lo maneja bastante bien :)
protoEvangelion

2

Si está utilizando intelliJ como IDE Intente fusionar padre a su rama por

git checkout <localbranch>
git merge origin/<remotebranch>

Mostrará todos los conflictos como este

A_MBPro: prueba anu $ git merge origin / Auto-merging src / test / java / com /.../ TestClass.java CONFLICT (content): Merge conflict in src / test / java / com /.../ TestClass.java

Ahora tenga en cuenta que el archivo TestClass.java se muestra en rojo en intelliJ También se mostrará el estado de git

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

Abra el archivo en intelliJ, tendrá secciones con

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

donde HEAD es cambios en su sucursal local y origen / es cambios desde la sucursal remota. Aquí guarde las cosas que necesita y elimine las que no necesita. Después de eso, deberían seguir los pasos normales. Es decir

   git add TestClass.java
   git commit -m "commit message"
   git push

2

Estoy usando el Código Visual de Microsoft para resolver conflictos. Es muy simple de usar. Mantengo mi proyecto abierto en el espacio de trabajo. Detecta y resalta conflictos, además da opciones de GUI para seleccionar cualquier cambio que quiera mantener de HEAD o entrante. ingrese la descripción de la imagen aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.