web-dev-qa-db-fra.com

Comment utiliser vimdiff pour résoudre un conflit de fusion git?

Je viens de fusionner une branche dans mon maître dans git et j'ai eu Automatic merge failed; fix conflicts and then commit the result. Maintenant j'ai couru git mergetool et vimdiff s'ouvrent avec l'image ci-dessous. Je ne sais pas comment utiliser vimdiff. Que signifie chaque panneau ici et comment dois-je procéder pour résoudre le conflit de fusion?

enter image description here

134
Cool Guy Yo

Les quatre mémoires tampons fournissent une vue différente du même fichier. Le tampon en haut à gauche (LOCAL) correspond à l'apparence du fichier dans votre branche cible (en quoi vous fusionnez). Le tampon en haut à droite (REMOTE) correspond à l'apparence du fichier dans votre branche source (à partir de laquelle vous effectuez la fusion). Le tampon central (BASE) est l’ancêtre commun des deux (vous pouvez donc comparer les différences entre les versions gauche et droite).

Je peux me tromper sur le point suivant. Je pense que la source du conflit de fusion est que les deux fichiers ont changé la même partie du fichier depuis BASE; LOCAL a changé les guillemets de doubles en simples, et REMOTE a fait le même changement mais a également changé la valeur d'arrière-plan d'une couleur à une URL. (Je pense que la fusion n'est pas assez intelligente pour remarquer que tous les changements apportés à LOCAL sont également présents dans REMOTE; il sait simplement que LOCAL a effectué des changements depuis BASE aux mêmes endroits que REMOTE).

Dans tous les cas, le tampon inférieur contient le fichier que vous pouvez réellement éditer, celui qui se trouve dans votre répertoire de travail. Vous pouvez apporter les modifications souhaitées. vim vous montre en quoi elle diffère de chacune des vues de dessus, qui sont les zones que la fusion automatique ne pouvait pas gérer. Tirez les changements de LOCAL si vous ne voulez pas les changements à distance. Tirez les changements de REMOTE si vous préférez ceux-ci aux changements LOCAUX. Tirez de BASE si vous pensez que REMOTE et LOCAL sont incorrects. Faites quelque chose de complètement différent si vous avez une meilleure idée! En fin de compte, les modifications que vous apportez ici sont celles qui seront réellement engagées.

124
chepner

La réponse de @ chepner est excellente, je voudrais ajouter quelques détails sur la partie "de la procédure à suivre pour résoudre le conflit de fusion". Si vous regardez comment utiliser réellement vimdiff dans ce cas, cela ira plus bas.


Tout d’abord, adressez-vous à l’option "Tout annuler" - si vous ne souhaitez pas utiliser "vimdiff" et que vous souhaitez annuler la fusion: appuyez sur Esc, puis tapez :qa! et frapper Enter. (voir aussi Comment puis-je quitter l'éditeur Vim? ). Git vous demandera si la fusion est complète, répondez avec n.


Si vous souhaitez utiliser vimdiff, voici quelques raccourcis utiles. Cela suppose que vous connaissez les bases de Vim (navigation et mode insertion/normal):

  • accédez au tampon inférieur (résultat de la fusion): Ctrl-Wj
  • accédez au prochain diff avec j/k; ou, mieux, utilisez ]c et [c pour naviguer respectivement au diff précédent et précédent
  • utilisation zo alors que sur un pli pour l'ouvrir, si vous voulez voir plus de contexte
  • pour chaque diff, selon la réponse de @ chepner, vous pouvez obtenir le code à partir d'une version locale, distante ou de base, ou le modifier et le rétablir à votre guise
    • pour l'obtenir à partir de la version locale, utilisez :diffget LO
    • de la télécommande: :diffget RE
    • de la base: :diffget BA
    • ou, si vous souhaitez modifier le code vous-même, obtenez d'abord une version de local/remote/base, puis passez en mode insertion et modifiez le reste
  • ceci fait, enregistrez le résultat de la fusion et quittez toutes les fenêtres :wqa
  • normalement, git détecte que la fusion a été faite et crée le commit de fusion

Il ne semble pas possible d'ajouter des éléments de conflit locaux et distants sans copier-coller ni raccourcis personnalisés: https://vi.stackexchange.com/questions/10534/is-there-a-way-to- take-both-when-using-vim-as-merge-tool , ce qui est dommage, car add add est un type de conflit courant.

Pour empêcher vimdiff de vous demander d’appuyer sur Entrée à chaque démarrage, ajoutez à votre .vimrc:

set shortmess=Ot

comme mentionné à: https://vi.stackexchange.com/questions/771/how-can-i-suppress-the-press-enter-Prompt-when-opening-files-in-diff-mode

Vous pouvez rechercher sur Internet d'autres raccourcis vimdiff. J'ai trouvé celui-ci utile: https://Gist.github.com/hyamamoto/7783966

54
Timur

Comment différencier entre (BASE et LOCAL) et (BASE et REMOTE) avec vim -d

Lors de la résolution des conflits de fusion, l'une des choses les plus importantes à voir est la suivante:

  • comment mon nouveau commit a-t-il changé le commit de base
  • comment le commit existant a-t-il modifié le commit de base

pour ensuite essayer de les mettre ensemble.

Bien que vimdiff fasse un bon travail en montrant côte à côte tous les types BASE, LOCAL et REMOTE, je ne peux pas clairement voir les deux diffs distincts de BASE:

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

Pour résoudre ce problème, j’ai remarqué que, alors que git mergetool exécute vimdiff, s'il existe un conflit sur un fichier nommé, disons main.py, git génère des fichiers pour chacune des versions, nommés ainsi:

main_BASE_1367.py
main_LOCAL_1367.py
main_REMOTE_1367.py

dans le même répertoire que main.py1367 est le PID de git mergetool, et donc un entier "aléatoire", comme indiqué à: Dans un conflit de fusion de git, quels sont les fichiers BACKUP, BASE, LOCAL et REMOTE générés?

Donc, pour voir les diffs que je veux, je commence par trouver les fichiers générés avec git status, puis ouvrez de nouveaux terminaux et faites un vimdiff entre les paires de fichiers qui me tiennent à cœur:

vim -d main_BASE_1367.py main_LOCAL_1367.py
vim -d main_BASE_1367.py main_REMOTE_1367.py

Ensemble avec git mergetool, cette information aide beaucoup à comprendre rapidement ce qui se passe!

De plus, même si mergetool est en cours d'exécution, vous pouvez simplement ouvrir le fichier:

vim main.py

directement et éditez-le ici si vous pensez que ce sera plus facile avec une plus grande fenêtre d’éditeur.

Je suppose que nous pourrions automatiser encore davantage pour ouvrir automatiquement tous ces fichiers, mais je ne me suis pas encore aventuré là-bas.

Aller directement à la fusion des conflits

Tandis que ]c saute au prochain point de diff dans vimdiff, il n’ya pas toujours de conflit de fusion.

Pour aider avec ceci, j'ai dans mon ~/.vimrc:

# Git Merge conflict
nnoremap <leader>gm /\v^\<\<\<\<\<\<\< \|\=\=\=\=\=\=\=$\|\>\>\>\>\>\>\> /<cr>

qui trouve les conflits directement.