Comment résoudre les conflits de fusion dans Git

4769

Comment résoudre les conflits de fusion dans Git?

Spoike
la source
31
Le billet de blog suivant semble donner un très bon exemple sur la façon de gérer les conflits de fusion avec Git qui devrait vous aider à aller dans la bonne direction. Gérer et éviter les conflits à Git
mwilliams
4
Vous pouvez configurer un outil de fusion (kdiff3 jebaird.com/2013/07/08/… ) puis utiliser git mergetool. Lorsque vous travaillez dans de grandes équipes de développeurs, vous rencontrerez toujours des conflits de fusion.
Grady G Cooper
N'oubliez pas que vous pouvez atténuer la plupart des conflits de fusion en fusionnant régulièrement en aval!
Ant P
8
Question fascinante: posée en 2008, 100% ouverte sans aucune indication sur ce dont il s'agit vraiment (s'agit-il de l'interface graphique? Des commandes git? De la sémantique? De la poussée / traction ou simplement des conflits généraux?) - complètement sans réponse. 30 réponses, toutes (pour autant qu'un rapide coup d'œil le montre) plus ou moins sur différents outils de diff3 et de fusion, aucune acceptée. La réponse la plus votée mentionne une commande qui ne fonctionne même pas prête à l'emploi avec une gitinstallation par défaut . J'ai réussi à accéder à la page de démarrage SE pour moi aujourd'hui, 2017, avec 1,3 million de vues et des milliers de votes dans les deux sens. Fascinant.
AnoE

Réponses:

2913

Essayer: git mergetool

Il ouvre une interface graphique qui vous guide à travers chaque conflit, et vous pouvez choisir comment fusionner. Parfois, cela nécessite un peu de retouche manuelle par la suite, mais généralement c'est suffisant en soi. C'est bien mieux que de faire le tout à la main certainement.

Selon le commentaire de @JoshGlover:

La commande

n'ouvre pas nécessairement une interface graphique, sauf si vous en installez une. Courir git mergetoolpour moi a vimdiffété utilisé. Vous pouvez installer l' un des outils suivants pour l' utiliser à la place: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

Voici l'exemple de procédure à utiliser vimdiffpour résoudre les conflits de fusion. Basé sur ce lien

Étape 1 : exécutez les commandes suivantes dans votre terminal

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

Cela définira vimdiff comme outil de fusion par défaut.

Étape 2 : exécuter la commande suivante dans le terminal

git mergetool

Étape 3 : Vous verrez un affichage vimdiff au format suivant

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

Ces 4 vues sont

LOCAL - c'est un fichier de la branche courante

BASE - ancêtre commun, à quoi ressemblait le fichier avant les deux changements

REMOTE - fichier que vous fusionnez dans votre branche

FUSION - résultat de la fusion, c'est ce qui est enregistré dans le référentiel

Vous pouvez naviguer parmi ces vues à l'aide de ctrl+ w. Vous pouvez accéder directement à la vue FUSION avec ctrl+ wsuivi de j.

Plus d'informations sur la navigation vimdiff ici et ici

Étape 4 . Vous pouvez modifier la vue fusionnée de la manière suivante

Si vous souhaitez obtenir des modifications de REMOTE

:diffg RE  

Si vous souhaitez obtenir des modifications de BASE

:diffg BA  

Si vous souhaitez obtenir des modifications de LOCAL

:diffg LO 

Étape 5 . Enregistrer, quitter, valider et nettoyer

:wqa enregistrer et quitter vi

git commit -m "message"

git clean Supprimez les fichiers supplémentaires (par exemple * .orig) créés par l'outil diff.

Peter Burns
la source
54
Pour info, vous pouvez utiliser git mergetool -ypour enregistrer quelques frappes si vous fusionnez un grand nombre de fichiers à la fois.
davr
373
Eh bien, cela n'ouvre pas nécessairement une interface graphique, sauf si vous en installez une. Courir git mergetoolpour moi a vimdiffété utilisé. Vous pouvez installer l' un des outils suivants pour l' utiliser à la place: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge.
Josh Glover
31
Bon point Josh. Sur Ubuntu, j'ai eu la meilleure chance avec Meld, son affichage de fusion à trois voies n'est pas mauvais. Sur OSX, git a choisi une belle valeur par défaut.
Peter Burns
18
Cela a ouvert KDiff3. Ce que je ne sais absolument pas comment utiliser.
David Murdoch
7
Vous pouvez également utiliser Beyond Compare 3 maintenant ( git mergetool -t bc3).
AzP
1703

Voici un cas d'utilisation probable, d'en haut:

Vous allez apporter quelques changements, mais oups, vous n'êtes pas à jour:

git fetch origin
git pull origin master

From ssh://[email protected]:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Vous vous mettez à jour et réessayez, mais vous avez un conflit:

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

From ssh://[email protected]: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.

Vous décidez donc de jeter un œil aux changements:

git mergetool

Oh mon, oh mon, en amont changé certaines choses, mais juste pour utiliser mes changements ... non ... leurs changements ...

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

Et puis on essaie une dernière fois

git pull origin master

From ssh://[email protected]:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!

CoolAJ86
la source
19
Cela a été très utile car j'ai eu beaucoup d'erreurs de fusion avec des fichiers binaires (éléments artistiques) et leur fusion semble toujours échouer, donc je dois toujours l'écraser avec le nouveau fichier et non "fusionner"
petrocket
188
Prudent! Le sens de - nos et - leurs est inversé. --ours == la télécommande. --les == locaux. Voirgit merge --help
mmell
57
Dans mon cas, je confirme que --theirs = référentiel distant, --ours = mon propre référentiel local. C'est l'opposé des commentaires de @mmell.
Aryo
24
@mmell Seulement sur un rebase, apparemment. Voirthis question
Navin
184
Les gars, «les nôtres» et «les leurs» sont liés au fait que vous fusionniez ou rebasiez ou non. Si vous fusionnez , «nôtre» signifie la branche dans laquelle vous fusionnez et «leur» est la branche dans laquelle vous fusionnez. Lorsque vous rebasez , «nôtre» signifie les commits sur lesquels vous rebasez. , tandis que "leur" fait référence aux validations que vous souhaitez rebaser.
736

Je trouve que les outils de fusion m'aident rarement à comprendre le conflit ou la résolution. Je réussis généralement mieux à regarder les marqueurs de conflit dans un éditeur de texte et à utiliser git log comme supplément.

Voici quelques conseils:

Astuce un

La meilleure chose que j'ai trouvée est d'utiliser le style de conflit de fusion "diff3":

git config merge.conflictstyle diff3

Cela produit des marqueurs de conflit comme celui-ci:

<<<<<<<
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 section du milieu est à quoi ressemblait l'ancêtre commun. Ceci est utile car vous pouvez le comparer aux versions supérieure et inférieure pour avoir une meilleure idée de ce qui a été modifié sur chaque branche, ce qui vous donne une meilleure idée de l'objectif de chaque modification.

Si le conflit n'est que de quelques lignes, cela rend généralement le conflit très évident. (Savoir comment résoudre un conflit est très différent; vous devez savoir sur quoi travaillent les autres. Si vous êtes confus, il est probablement préférable d'appeler cette personne dans votre chambre pour qu'elle puisse voir ce que vous cherchez. à.)

Si le conflit est plus long, je vais couper et coller chacune des trois sections dans trois fichiers distincts, tels que "le mien", "commun" et "le leur".

Ensuite, je peux exécuter les commandes suivantes pour voir les deux mecs diff qui ont provoqué le conflit:

diff common mine
diff common theirs

Ce n'est pas la même chose que d'utiliser un outil de fusion, car un outil de fusion comprendra également tous les morceaux de diff non conflictuels. Je trouve cela distrayant.

Astuce deux

Quelqu'un l'a déjà mentionné, mais comprendre l'intention derrière chaque morceau diff est généralement très utile pour comprendre d'où vient un conflit et comment le gérer.

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

Cela montre tous les commits qui ont touché ce fichier entre l'ancêtre commun et les deux têtes que vous fusionnez. (Il n'inclut donc pas les validations qui existent déjà dans les deux branches avant la fusion.) Cela vous aide à ignorer les morceaux différents qui ne sont clairement pas un facteur dans votre conflit actuel.

Troisième conseil

Vérifiez vos modifications avec des outils automatisés.

Si vous avez des tests automatisés, exécutez-les. Si vous avez des peluches , lancez-le. Si c'est un projet à construire, alors construisez-le avant de vous engager, etc. Dans tous les cas, vous devez faire un peu de test pour vous assurer que vos modifications n'ont rien cassé. (Heck, même une fusion sans conflits peut casser le code de travail.)

Astuce quatre

Planifier à l'avance; communiquer avec des collègues.

Planifier à l'avance et être conscient de ce sur quoi les autres travaillent peut aider à prévenir les conflits de fusion et / ou à les résoudre plus tôt - alors que les détails sont encore frais à l'esprit.

Par exemple, si vous savez que vous et une autre personne travaillez tous les deux sur une refactorisation différente qui affectera à la fois le même ensemble de fichiers, vous devriez vous parler à l'avance et avoir une meilleure idée des types de changements que chacun de vous est fabrication. Vous pourriez économiser beaucoup de temps et d'efforts si vous effectuez les changements prévus en série plutôt qu'en parallèle.

Pour les remaniements majeurs qui traversent une large bande de code, vous devriez fortement envisager de travailler en série: tout le monde arrête de travailler sur cette zone du code pendant qu'une personne effectue le refactoring complet.

Si vous ne pouvez pas travailler en série (en raison de contraintes de temps, peut-être), alors communiquer sur les conflits de fusion attendus vous aide au moins à résoudre les problèmes plus tôt tandis que les détails sont encore frais à l'esprit. Par exemple, si un collègue effectue une série de commissions perturbatrices au cours d'une période d'une semaine, vous pouvez choisir de fusionner / rebaser sur cette branche de collègues une ou deux fois par jour pendant cette semaine. De cette façon, si vous trouvez des conflits de fusion / rebase, vous pouvez les résoudre plus rapidement que si vous attendez quelques semaines pour tout fusionner en un seul gros morceau.

Astuce cinq

Si vous n'êtes pas sûr d'une fusion, ne la forcez pas.

La fusion peut sembler écrasante, surtout lorsqu'il y a beaucoup de fichiers en conflit et que les marqueurs de conflit couvrent des centaines de lignes. Souvent, lorsque nous estimons des projets logiciels, nous n'incluons pas suffisamment de temps pour les éléments de surcharge tels que la gestion d'une fusion noueuse, donc cela ressemble à un vrai frein de passer plusieurs heures à disséquer chaque conflit.

À long terme, planifier à l'avance et être conscient de ce sur quoi les autres travaillent sont les meilleurs outils pour anticiper les conflits de fusion et vous préparer à les résoudre correctement en moins de temps.

Mark E. Haase
la source
6
L'option diff3 est une excellente fonctionnalité à avoir avec les fusions. La seule interface graphique que j'ai rencontrée montre qu'il s'agit de Perforce p4merge, qui peut être installé et utilisé séparément des autres outils de Perforce (dont je n'ai pas utilisé, mais dont j'ai entendu des plaintes).
alxndr
3
Après une tentative de rebase qui a entraîné un conflit de fusion: $ git log --merge -p build.xml sortie: fatal: --merge sans MERGE_HEAD?
Ed Randall
que faire si j'ai des changements sur un fichier de branch1 et la suppression de ce fichier dans branch2. Comment puis-je résoudre ce conflit de fusion? Existe-t-il un moyen d'utiliser git où je peux les fusionner en conservant les modifications d'une branche?
Honey
git config merge.conflictstyle diff3- Merci Monsieur. C'est incroyable et cela m'a libéré d'essayer de trouver (et de payer $$) pour une bonne interface graphique de fusion à 3 voies. IMO, c'est mieux car il montre l'ancêtre commun ainsi que local / distant et affiche les dernières lignes de journal de validation que (AFAIK) aucune interface graphique ne fait. Les commits vous aident certainement à identifier quel code appartient à quelle branche.
ffxsam du
J'ai trouvé que parfois le conflitstyle diff3 aboutit à d'énormes morceaux de diff qui sont en grande partie identiques, tandis que la valeur par défaut produira des morceaux plus petits et plus faciles à gérer. Malheureusement, je n'ai pas de reproducteur que je puisse utiliser pour un rapport de bogue. Mais si vous rencontrez ce problème, vous pouvez envisager de désactiver temporairement cette option.
Dave Abrahams
348
  1. Identifiez les fichiers en conflit (Git devrait vous le dire).

  2. Ouvrez chaque fichier et examinez les différences; Git les délimite. Avec un peu de chance, il sera évident quelle version de chaque bloc conserver. Vous devrez peut-être en discuter avec d'autres développeurs qui ont validé le code.

  3. Une fois que vous avez résolu le conflit dans un fichier git add the_file.

  4. Une fois que vous avez résolu tous les conflits, exécutez git rebase --continueou n'importe quelle commande que Git a dit de faire lorsque vous avez terminé.

davetron5000
la source
38
@Justin Considérez Git comme un suivi de contenu plutôt que de suivi de fichiers. Ensuite, il est facile de voir que le contenu que vous avez mis à jour n'est pas dans le référentiel et doit être ajouté. Cette façon de penser explique également pourquoi Git ne suit pas les dossiers vides: bien qu'il s'agisse techniquement de fichiers, il n'y a pas de contenu à suivre.
Gareth
7
le contenu est là, le conflit se produit parce qu'il y a 2 version du contenu. Par conséquent, "git add" ne semble pas correct. Et cela ne fonctionne pas (git add, git commit) si vous ne voulez valider qu'un seul fichier après la résolution du conflit ("fatal: impossible de faire un commit partiel pendant une fusion.")
Dainius
1
Oui, techniquement, cela répond à la question qui, comme posée, mais n'est pas une réponse utilisable, à mon avis, désolé. Quel est l' intérêt de rendre une branche identique à une autre? Bien sûr, une fusion aura des conflits ..
Thufir
5
Thulfir: qui a dit quoi que ce soit pour faire d'une branche la même chose qu'une autre? Il existe différents scénarios où vous devez fusionner, sans «rendre une branche identique à une autre». L'une est lorsque vous avez terminé avec une branche de développement et que vous souhaitez intégrer ses modifications dans la branche principale; après cela, la branche de développement peut être supprimée. Un autre est lorsque vous souhaitez rebaser votre branche de développement, afin de faciliter la fusion finale éventuelle dans le maître.
Teemu Leisti
4
@JustinGrant git addmet en scène les fichiers dans l'index; il ne pas ajouter quoi que ce soit au dépôt. git commitajoute des éléments au référentiel. Cette utilisation est logique pour les fusions - la fusion met automatiquement en scène toutes les modifications qui peuvent être fusionnées automatiquement; il vous appartient de fusionner les autres modifications et de les ajouter à l'index lorsque vous avez terminé.
Mark E. Haase
105

Consultez les réponses à la question Stack Overflow Abandonner une fusion dans Git , en particulier la réponse de Charles Bailey qui montre comment afficher les différentes versions du fichier avec des problèmes, par exemple,

# 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
Pat Notz
la source
Consultez également l'option "-m" pour "git checkout -m" - cela vous permet d'extraire les différentes mouches dans votre espace de travail
qneill
Cela m'a sauvé. L'examen de chaque fichier séparément m'a permis de me rappeler ce que j'allais faire dans chaque branche. Ensuite, je pourrais prendre la décision de choisir.
Rohmer
99

Les conflits de fusion se produisent lorsque des modifications sont apportées à un fichier en même temps. Voici comment le résoudre.

git CLI

Voici les étapes simples que faire lorsque vous êtes en conflit:

  1. Notez la liste des fichiers en conflit avec: git status(sous la Unmerged pathssection).
  2. Résolvez les conflits séparément pour chaque fichier par l'une des approches suivantes:

    • Utilisez l'interface graphique pour résoudre les conflits: git mergetool(la manière la plus simple).

    • Pour accepter à distance / autre version, utilisez: git checkout --theirs path/file. Cela rejettera toutes les modifications locales que vous avez apportées à ce fichier.

    • Pour accepter la version locale / notre version, utilisez: git checkout --ours path/file

      Cependant, vous devez être prudent, car les modifications à distance que les conflits ont été faites pour une raison quelconque.

      Connexes: Quelle est la signification précise de "nôtre" et "leur" dans git?

    • Modifiez les fichiers en conflit manuellement et recherchez le bloc de code entre <<<<</ >>>>>puis choisissez la version ci-dessus ou ci-dessous =====. Voir: Comment les conflits sont présentés .

    • Les conflits de chemin et de nom de fichier peuvent être résolus par git add/ git rm.

  3. Enfin, passez en revue les fichiers prêts à être validés en utilisant: git status .

    Si vous avez encore des fichiers sous Unmerged pathset que vous avez résolu le conflit manuellement, faites savoir à Git que vous l'avez résolu en:git add path/file .

  4. Si tous les conflits ont été résolus avec succès, validez les modifications en: git commit -a et poussez sur remote comme d'habitude.

Voir également: Résolution d'un conflit de fusion à partir de la ligne de commande sur GitHub

Pour un didacticiel pratique, consultez: Scénario 5 - Résolution des conflits de fusion par Katacoda .

DiffMerge

J'ai utilisé avec succès DiffMerge qui peut comparer visuellement et fusionner des fichiers sur Windows, macOS et Linux / Unix.

Il peut représenter graphiquement les changements entre 3 fichiers et il permet une fusion automatique (lorsque cela est sûr) et un contrôle total sur l'édition du fichier résultant.

DiffMerge

Source de l'image: DiffMerge (capture d'écran Linux)

Il suffit de le télécharger et de l'exécuter dans le référentiel en tant que:

git mergetool -t diffmerge .

macOS

Sur macOS, vous pouvez installer via:

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

Et probablement (si non fourni) vous avez besoin du wrapper extra simple suivant placé dans votre PATH (par exemple /usr/bin):

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

Ensuite, vous pouvez utiliser les raccourcis clavier suivants:

  • - Alt- Up/Down pour passer aux modifications précédentes / suivantes.
  • - Alt- Left/ Rightpour accepter le changement de gauche ou de droite

Alternativement, vous pouvez utiliser opendiff (qui fait partie des outils Xcode) qui vous permet de fusionner deux fichiers ou répertoires ensemble pour créer un troisième fichier ou répertoire.

kenorb
la source
79

Si vous effectuez fréquemment de petites validations, commencez par regarder les commentaires de validation avec git log --merge. Ensuite git diff, vous montrera les conflits.

Pour les conflits qui impliquent plusieurs lignes, il est plus facile de voir ce qui se passe dans un outil GUI externe. J'aime opendiff - Git prend également en charge vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, sortent de la boîte et vous pouvez en installer d'autres: git config merge.tool "your.tool"définira l'outil choisi, puisgit mergetool après une fusion échouée, vous montrera les différences dans le contexte.

Chaque fois que vous modifiez un fichier pour résoudre un conflit, git add filenamemettra à jour l'index et votre diff ne l'affichera plus. Lorsque tous les conflits seront traités et que leurs fichiers auront été git addsupprimés, git commitla fusion sera terminée.

Paul
la source
8
Utiliser "git add" est la vraie astuce ici. Vous ne voudrez peut-être même pas vous engager (peut-être que vous voulez ranger), mais vous devez faire "git add" pour terminer la fusion. Je pense que mergetool fait l'ajout pour vous (bien qu'il ne soit pas dans la page de manuel), mais si vous faites la fusion manuellement, vous devez utiliser "git add" pour le terminer (même si vous ne voulez pas vous engager).
nobar
47

Voir Comment les conflits sont présentés ou, dans Git, la git mergedocumentation pour comprendre ce que sont les marqueurs de conflit de fusion.

De plus, la section Comment résoudre les conflits explique comment résoudre les conflits:

Après avoir vu un conflit, vous pouvez faire deux choses:

  • Décidez de ne pas fusionner. Les seuls nettoyages dont vous avez besoin sont de réinitialiser le fichier d'index au HEADcommit pour inverser 2. et de nettoyer les modifications de l'arborescence de travail effectuées par 2. et 3 .; git merge --abortpeut être utilisé pour cela.

  • Résolvez les conflits. Git marquera les conflits dans l'arborescence de travail. Modifiez les fichiers en forme et git addles indexer. Utilisez git commitpour sceller l'accord.

Vous pouvez résoudre le conflit avec un certain nombre d'outils:

  • Utilisez un mergetool. git mergetoolpour lancer un mergetool graphique qui vous aidera tout au long de la fusion.

  • Regardez les différences. git diffaffichera un diff à trois voies, mettant en évidence les changements à la fois des versions HEADet MERGE_HEAD.

  • Regardez les différences de chaque branche. git log --merge -p <path>affichera d'abord les différences pour la HEADversion, puis la MERGE_HEADversion.

  • Regardez les originaux. git show :1:filenameaffiche l'ancêtre commun, git show :2:filenameaffiche la HEADversion et git show :3:filenameaffiche la MERGE_HEADversion.

Vous pouvez également lire sur les marqueurs de conflit de fusion et comment les résoudre dans la section du livre Pro Git Conflits de fusion de base .

Peter Mortensen
la source
42

Je veux soit ma ou leur version complète, soit je veux examiner les modifications individuelles et décider pour chacune d'entre elles.

Accepter entièrement ma ou leur version :

Acceptez ma version (locale, la nôtre):

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

Acceptez leur version (à distance, la leur):

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

Si vous souhaitez exécuter tous les fichiers de conflit, exécutez:

git merge --strategy-option ours

ou

git merge --strategy-option theirs

Passez en revue toutes les modifications et acceptez-les individuellement

  1. git mergetool
  2. Examinez les modifications et acceptez l'une ou l'autre version pour chacune d'entre elles.
  3. git add <filename>
  4. git commit -m "merged bla bla"

La valeur par défaut mergetoolfonctionne en ligne de commande . Comment utiliser un mergetool en ligne de commande devrait être une question distincte.

Vous pouvez également installer un outil visuel pour cela, par exemple meldet exécuter

git mergetool -t meld

Il ouvrira la version locale (la nôtre), la version "de base" ou "fusionnée" (le résultat actuel de la fusion) et la version distante (la leur). Enregistrez la version fusionnée lorsque vous avez terminé, exécutez à git mergetool -t meldnouveau jusqu'à ce que vous obteniez «Aucun fichier n'a besoin d'être fusionné», puis passez aux étapes 3. et 4.

Aucune idée
la source
Cette commande: git checkout --theirs - <filename> a changé TOUS les fichiers en leur, pas seulement <filename>
Donato
En fait, j'avais tort. Cela met uniquement à jour le fichier spécifié.
Donato
40

Pour les utilisateurs d' Emacs qui souhaitent résoudre les conflits de fusion de manière semi-manuelle:

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

affiche tous les fichiers qui nécessitent une résolution de conflit.

Ouvrez chacun de ces fichiers un par un ou tous en même temps en:

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

Lorsque vous visitez un tampon nécessitant des modifications dans Emacs, tapez

ALT+x vc-resolve-conflicts

Cela ouvrira trois tampons (le mien, le leur et le tampon de sortie). Naviguez en appuyant sur «n» (région suivante), «p» (région de prévision). Appuyez sur 'a' et 'b' pour copier respectivement la mienne ou la leur dans le tampon de sortie. Et / ou modifiez directement le tampon de sortie.

Une fois terminé: Appuyez sur 'q'. Emacs vous demande si vous souhaitez enregistrer ce tampon: oui. Après avoir terminé un tampon, marquez-le comme résolu en exécutant le teriminal:

git add FILENAME

Une fois terminé avec tous les types de tampons

git commit

pour terminer la fusion.

eci
la source
33

Prime:

En parlant de pull / fetch / merge dans les réponses ci-dessus, je voudrais partager une astuce intéressante et productive,

git pull --rebase

Cette commande ci-dessus est la commande la plus utile de ma vie git qui a permis de gagner beaucoup de temps.

Avant de pousser votre modification nouvellement validée sur le serveur distant, essayez git pull --rebaseplutôt git pullet manuellementmerge et il synchronisera automatiquement les dernières modifications du serveur distant (avec une extraction + fusion) et placera votre dernière validation locale en haut dans le journal git. Pas besoin de s'inquiéter de l'extraction / fusion manuelle.

En cas de conflit, utilisez simplement

git mergetool
git add conflict_file
git rebase --continue

Plus de détails sur: http://gitolite.com/git-pull--rebase

Sazzad Hissain Khan
la source
32

Simplement, si vous savez bien que les changements dans l'un des référentiels ne sont pas importants et que vous souhaitez résoudre tous les changements en faveur de l'autre, utilisez:

git checkout . --ours

pour résoudre les modifications en faveur de votre référentiel , ou

git checkout . --theirs

pour résoudre les changements en faveur de l' autre ou du référentiel principal .

Sinon, vous devrez utiliser un outil de fusion GUI pour parcourir les fichiers un par un, dire que l'outil de fusion est p4mergeou écrire le nom de quelqu'un que vous avez déjà installé

git mergetool -t p4merge

et après avoir terminé un fichier, vous devrez enregistrer et fermer, donc le suivant s'ouvrira.

Mohamed Selim
la source
2
git checkout. --ils ont résolu mon problème grâce
Ramesh Chand
si vous préférez résoudre les conflits manuellement, essayez d'ouvrir le dossier dans Visual Studio Code, il marque les fichiers avec des conflits et colore les lignes de conflit à l'intérieur de chacun
Mohamed Selim
31

Veuillez suivre les étapes suivantes pour résoudre les conflits de fusion dans Git:

  1. Vérifiez le statut Git: statut git

  2. Obtenez le patchset: git fetch ( récupérez le bon patch depuis votre commit Git)

  3. Extraire une branche locale (temp1 dans mon exemple ici): git checkout -b temp1

  4. Extraire le contenu récent de master: git pull --rebase origin master

  5. Démarrez le mergetool et vérifiez les conflits et corrigez-les ... et vérifiez les modifications dans la branche distante avec votre branche actuelle: git mergetool

  6. Vérifiez à nouveau l'état: git status

  7. Supprimez les fichiers indésirables créés localement par mergetool, généralement mergetool crée un fichier supplémentaire avec l'extension * .orig. Veuillez supprimer ce fichier car il ne s'agit que du doublon et corriger les modifications localement et ajouter la version correcte de vos fichiers. git add #your_changed_correct_files

  8. Vérifiez à nouveau l'état: git status

  9. Validez les modifications sur le même ID de validation (cela évite un nouvel ensemble de correctifs séparé): git commit --amend

  10. Push vers la branche master: git push (vers votre dépôt Git)

Chhabilal
la source
28

Il y a 3 étapes:

  1. Rechercher les fichiers provoquant des conflits par commande

    git status
    
  2. Vérifiez les fichiers dans lesquels vous trouverez les conflits marqués comme

    <<<<<<<<head
    blablabla
    
  3. Modifiez-le comme vous le souhaitez, puis validez avec les commandes

    git add solved_conflicts_files
    git commit -m 'merge msg'
    
Qijun Liu
la source
A travaillé pour moi! Merci!
Nuwan Jayawardene du
Vous devez faire attention si vous le faites lors du rebasage. Vous devez utiliser git rebase --continue au lieu de git commit
Samuel Dauzon
27

Vous pouvez résoudre les conflits de fusion de plusieurs manières, comme d'autres l'ont détaillé.

Je pense que la vraie clé est de savoir comment les changements se déroulent avec les référentiels locaux et distants. La clé pour cela est de comprendre les branches de suivi. J'ai trouvé que je considère la branche de suivi comme la `` pièce manquante au milieu '' entre moi mon répertoire de fichiers local et réel et la télécommande définie comme origine.

J'ai personnellement pris l'habitude de 2 choses pour éviter cela.

Au lieu de:

git add .
git commit -m"some msg"

Ce qui a deux inconvénients -

a) Tous les fichiers nouveaux / modifiés sont ajoutés et cela peut inclure des modifications indésirables.
b) Vous ne pouvez pas consulter la liste des fichiers en premier.

Donc à la place je fais:

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

De cette façon, vous êtes plus délibéré sur les fichiers à ajouter et vous pouvez également consulter la liste et réfléchir un peu plus lorsque vous utilisez l'éditeur pour le message. Je trouve que cela améliore également mes messages de validation lorsque j'utilise un éditeur plein écran plutôt que l' -moption.

[Mise à jour - au fil du temps, je suis passé à plus:

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

]

Aussi (et plus pertinent pour votre situation), j'essaye d'éviter:

git pull

ou

git pull origin master.

car pull implique une fusion et si vous avez des modifications localement que vous ne vouliez pas fusionner, vous pouvez facilement vous retrouver avec du code fusionné et / ou des conflits de fusion pour du code qui n'aurait pas dû être fusionné.

Au lieu de cela, j'essaie de faire

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

Vous pouvez également trouver cela utile:

git branch, fork, fetch, merge, rebase and clone, quelles sont les différences?

Michael Durrant
la source
Hé, j'ai un peu compris ta réponse. Mais comme je suis nouveau dans les conflits de fusion github, je pense qu'il manque quelque chose. Qu'advient-il de vos modifications locales lorsque vous le faites git checkout masteret git fetch et git rebase --hard origin/master
Suhaib
Je pense que vous devriez ajouter plus de détails sur ce que vous devez faire. Un autre exemple qui m'embrouille, vous l'avez mentionné dans votre réponse: git add .oui, cela sauvera-t-il nos modifications locales afin que nous puissions poursuivre git checkout master? ou s'agit-il de deux scénarios différents?
Suhaib
@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option hard 'usage: git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] ou: git rebase [-i] [ options] [--exec <cmd>] [--onto <newbase>] --root [<branch>] ou: git rebase --continue | --abort | --skip | --edit-todo `
likejudo
24

La réponse de CoolAJ86 résume à peu près tout. Si vous avez des changements dans les deux branches dans le même morceau de code, vous devrez effectuer une fusion manuelle. Ouvrez le fichier en conflit dans n'importe quel éditeur de texte et vous devriez voir la structure suivante.

(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)

Choisissez l'une des alternatives ou une combinaison des deux de la manière que vous souhaitez que le nouveau code soit, tout en supprimant les signes égaux et les crochets angulaires.

git commit -a -m "commit message"
git push origin master
iankit
la source
17
git log --merge -p [[--] path]

Ne semble pas toujours fonctionner pour moi et finit généralement par afficher chaque commit différent entre les deux branches, cela se produit même lors de l'utilisation -- pour séparer le chemin de la commande.

Ce que je fais pour contourner ce problème est d'ouvrir deux lignes de commande et en une seule fois

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

et dans l'autre

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

Remplacement $MERGED_IN_BRANCHpar la branche dans laquelle j'ai fusionné et [path]par le fichier en conflit. Cette commande enregistrera toutes les validations, sous forme de patch, entre ( ..) deux validations. Si vous laissez un côté vide comme dans les commandes ci-dessus, git utilisera automatiquement HEAD(la branche dans laquelle vous fusionnez dans ce cas).

Cela vous permettra de voir quels commits sont entrés dans le fichier dans les deux branches après leur divergence. Cela facilite généralement la résolution des conflits.

Brian Di Palma
la source
16

En utilisant patience

Je suis surpris que personne d'autre n'ait parlé de la résolution des conflits en utilisant patiencela stratégie récursive de fusion. Pour un gros conflit de fusion, en utilisantpatience m'a donné de bons résultats. L'idée est qu'il essaiera de faire correspondre les blocs plutôt que les lignes individuelles.

Si vous modifiez l'indentation de votre programme par exemple, la stratégie de fusion Git par défaut correspond parfois à des accolades simples {qui appartiennent à différentes fonctions. Ceci est évité avec patience:

git merge -s recursive -X patience other-branch

De la documentation:

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.

Comparaison avec l'ancêtre commun

Si vous avez un conflit de fusion et que vous voulez voir ce que les autres avaient en tête lors de la modification de leur branche, il est parfois plus facile de comparer directement leur branche avec l'ancêtre commun (au lieu de notre branche). Pour cela, vous pouvez utiliser merge-base:

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

Habituellement, vous souhaitez uniquement voir les modifications pour un fichier particulier:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>
Conchyliculteur
la source
Dans mon cas, cela n'a pas bien résolu les conflits de fusion, car pour une raison quelconque, il a conservé des lignes de configuration en double dans les projets C #. Bien qu'il soit plus convivial que TOUT LE FICHIER EST DIFFÉRENT, ce que j'avais auparavant
Mathijs Segers
15

Depuis le 12 décembre 2016, vous pouvez fusionner des succursales et résoudre des conflits sur github.com

Ainsi, si vous ne souhaitez pas utiliser la ligne de commande ou les outils tiers proposés ici à partir de réponses plus anciennes , utilisez l' outil natif de GitHub.

Cet article de blog explique en détail, mais les bases sont que lors de la `` fusion '' de deux branches via l'interface utilisateur, vous verrez désormais une option `` résoudre les conflits '' qui vous amènera à un éditeur vous permettant de gérer ces conflits de fusion.

entrez la description de l'image ici

maxwell
la source
ce n'est pas poser des questions sur github donc j'ai voté contre ce que je considère comme une très mauvaise réponse.
mschuett
1
@mschuett a raison, la question est "comment résoudre les conflits dans git", pas "comment résoudre les conflits dans github". Il y a une différence et il y a déjà beaucoup trop de gens qui pensent que git et github sont la même chose, donc tout ce qui propage ce sentiment est faux.
Patrick Mevzek
15

Si vous souhaitez fusionner de la branche (test) au maître, vous pouvez suivre ces étapes:

Étape 1 : allez à la succursale

git checkout test

Étape 2 :

git pull --rebase origin master

Étape 3 : S'il y a des conflits, accédez à ces fichiers pour le modifier.

Étape 4 : ajoutez ces modifications

git add #your_changes_files

Étape 5 :

git rebase --continue

Étape 6 : S'il y a toujours un conflit, revenez à l'étape 3. S'il n'y a pas de conflit, procédez comme suit:

git push origin +test

Étape 7 : Et puis il n'y a pas de conflit entre le test et le maître. Vous pouvez utiliser la fusion directement.

Haimei
la source
13

Je respecte toujours les étapes ci-dessous pour éviter les conflits.

  • git checkout master (Venez à la branche master)
  • git pull (Mettez à jour votre master pour obtenir le dernier code)
  • git checkout -b mybranch (Extraire une nouvelle branche et commencer à travailler sur cette branche pour que votre maître reste toujours en haut du tronc.)
  • git add. AND git commit AND git push (sur votre branche locale après vos modifications)
  • git checkout master (Revenez à votre maître.)

Maintenant, vous pouvez faire de même et maintenir autant de succursales locales que vous le souhaitez et travailler simultanément en effectuant une vérification de git dans votre succursale lorsque cela est nécessaire.

Chétan
la source
12

Des conflits de fusion peuvent survenir dans différentes situations:

  • Lors de l'exécution de "git fetch" puis de "git merge"
  • Lors de l'exécution de "git fetch" puis de "git rebase"
  • Lors de l'exécution de "git pull" (qui est en fait égal à l'une des conditions mentionnées ci-dessus)
  • Lors de l'exécution de "git stash pop"
  • Lorsque vous appliquez des correctifs git (validations exportées vers des fichiers à transférer, par exemple par e-mail)

Vous devez installer un outil de fusion compatible avec Git pour résoudre les conflits. J'utilise personnellement KDiff3, et je l'ai trouvé agréable et pratique. Vous pouvez télécharger sa version Windows ici:

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

BTW si vous installez Git Extensions, il y a une option dans son assistant de configuration pour installer Kdiff3.

Ensuite, configurez git configs pour utiliser Kdiff comme son outil de fusion:

$ 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

(N'oubliez pas de remplacer le chemin par le chemin réel du fichier exe Kdiff.)

Ensuite, chaque fois que vous rencontrez un conflit de fusion, il vous suffit d'exécuter cette commande:

$git mergetool

Ensuite, il ouvre le Kdiff3 et essaie d'abord de résoudre automatiquement les conflits de fusion. La plupart des conflits seraient résolus spontanément et vous devez corriger le reste manuellement.

Voici à quoi ressemble Kdiff3:

Entrez la description de l'image ici

Ensuite, une fois que vous avez terminé, enregistrez le fichier et il passe au fichier suivant avec conflit et vous recommencez jusqu'à ce que tous les conflits soient résolus.

Pour vérifier si tout a bien été fusionné, il suffit d'exécuter à nouveau la commande mergetool, vous devriez obtenir ce résultat:

$git mergetool
No files need merging
akazemis
la source
8

Cette réponse consiste à ajouter une alternative pour les utilisateurs de VIM comme I qui préfère tout faire dans l'éditeur.


TL; DR

entrez la description de l'image ici


Tpope est venu avec ce super plugin pour VIM appelé fugitif . Une fois installé, vous pouvez exécuter :Gstatuspour vérifier les fichiers qui sont en conflit et :Gdiffpour ouvrir Git de 3 manières.

Une fois dans la fusion à 3 voies, fugitive vous permettra d'obtenir les modifications de l'une des branches que vous fusionnez de la manière suivante:

  • :diffget //2, obtenez les modifications de la branche d'origine ( HEAD ):
  • :diffget //3, obtenez les modifications de la fusion de la branche:

Une fois la fusion du fichier terminée, saisissez :Gwritele tampon fusionné. Vimcasts a publié une excellente vidéo expliquant en détail ces étapes.

Vicente Bolea
la source
6

Gitlense pour VS Code

Vous pouvez essayer Gitlense pour VS Code, leurs principales caractéristiques sont les suivantes:

3. Résolvez facilement les conflits.

J'aime déjà cette fonctionnalité:

entrez la description de l'image ici

2. Blâme de la ligne actuelle.

entrez la description de l'image ici

3. Blâme de gouttière

entrez la description de l'image ici

4. Blâme de la barre d'état

entrez la description de l'image ici

Et il existe de nombreuses fonctionnalités que vous pouvez vérifier ici .

Ilyas karim
la source
5

git fetch
git checkout votre branche
git rebase master

Dans cette étape, vous essaierez de résoudre le conflit en utilisant votre IDE préféré

Vous pouvez suivre ce lien pour vérifier comment résoudre le conflit dans le fichier
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)

Maintenant tout va bien et vous trouverez votre commit dans gerrit

J'espère que cela aidera tout le monde concernant cette question.

Baini.Marouane
la source
3

Essayez Visual Studio Code pour l'édition si vous ne l'êtes pas déjà. Ce qu'il fait est après avoir essayé de fusionner (et atterrir dans des conflits de fusion). Le code VS détecte automatiquement les conflits de fusion.

Il peut vous aider très bien en montrant quelles sont les modifications apportées à l'original et si vous acceptez incomingou

current change(signifiant l'original avant de fusionner) '?.

Cela m'a aidé et ça peut aussi marcher pour vous!

PS: Cela ne fonctionnera que si vous avez configuré git avec votre code et Visual Studio Code.

Kailash Bhalaki
la source
2

Un moyen plus sûr de résoudre les conflits consiste à utiliser git-mediate (les solutions courantes suggérées ici sont à mon humble avis).

Voir cet article pour une introduction rapide sur la façon de l'utiliser.

yairchu
la source
2

Pour ceux qui utilisent Visual Studio (2015 dans mon cas)

  1. Fermez votre projet dans VS. Surtout dans les grands projets, VS a tendance à paniquer lors de la fusion à l'aide de l'interface utilisateur.

  2. Faites la fusion dans l'invite de commande.

    git checkout target_branch

    git merge source_branch

  3. Ouvrez ensuite le projet dans VS et accédez à Team Explorer -> Branch. Un message indique maintenant que la fusion est en attente et que les fichiers en conflit sont répertoriés juste en dessous du message.

  4. Cliquez sur le fichier en conflit et vous aurez la possibilité de fusionner, comparer, prendre la source, prendre la cible. L'outil de fusion dans VS est très facile à utiliser.

Mike
la source
J'utilise VS Code 2017 sur un très gros projet et je n'ai pas besoin de fermer le projet. Il le gère très bien :)
protoEvangelion
2

Si vous utilisez intelliJ comme IDE Essayez de fusionner le parent avec votre branche en

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

Il montrera tous les conflits comme celui-ci

A_MBPro: test anu $ git merge origin / Auto-merging src / test / java / com /.../ TestClass.java CONFLICT (content): Fusion du conflit dans src / test / java / com /.../ TestClass.java

Notez maintenant que le fichier TestClass.java est affiché en rouge dans intelliJ.

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

Ouvrez le fichier dans intelliJ, il aura des sections avec

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

où HEAD correspond aux modifications sur votre branche locale et à l'origine / correspond aux modifications de la branche distante. Ici, conservez les éléments dont vous avez besoin et supprimez ceux dont vous n'avez pas besoin, après quoi les étapes normales devraient suffire. C'est

   git add TestClass.java
   git commit -m "commit message"
   git push
AJC
la source
2

J'utilise le code visuel de Microsoft pour résoudre les conflits. C'est très simple à utiliser. Je garde mon projet ouvert dans l'espace de travail. Il détecte et met en évidence les conflits, donne en outre des options d'interface graphique pour sélectionner le changement que je souhaite conserver de HEAD ou entrant. entrez la description de l'image ici

Ammar Mujeeb
la source