web-dev-qa-db-fra.com

Git - comment forcer le conflit de fusion et la fusion manuelle sur le fichier sélectionné

Nous maintenons une application Web qui possède une branche maître commune et de nombreuses branches parallèles, une pour chaque installation, chacune comportant peu de modifications spécifiques. Le code source est géré dans git et c'est un outil formidable lorsque nous avons besoin de transférer des fonctionnalités et des corrections de bugs d'une branche principale vers une version parallèle. Mais rares sont les fichiers sensibles et la fusion automatique donne généralement de mauvais résultats. Ainsi, la fusion serait beaucoup plus facile si elles pouvaient être marquées d'une manière ou d'une autre et chaque fusion entraînerait un conflit nécessitant une fusion manuelle.

J'ai cherché une réponse:

  1. J'utilise les options de fusion --no-commit et --no-ff, mais ce n'est pas la même chose.
  2. Ici et ici quelqu'un pose la même question mais sans solution.
  3. Le cas similaire semble être comment empêcher la fusion de fichiers en utilisant .gitattributes contenant: somefile.php merge = our. J'ai essayé de trouver une option de fusion qui générerait un conflit ou une fusion manuelle forcée, mais je n'en ai trouvé aucune jusqu'à présent.
  4. Les fichiers .gitattributes contenant: somefile.php -merge ne sont jamais fusionnés automatiquement et imposent donc une fusion manuelle. C’est une solution à 90%, mais ce que je cherche, c’est d’essayer la fusion automatique et de la marquer comme un conflit, qu’il réussisse ou non. Mais ceci est pour l'instant le plus proche de la solution. _ {(... merci à Charles Bailey pour les éclaircissements ...)} _
  5. Quelqu'un suggère d’écrire un pilote de fusion personnalisé ( 1 , 2 ), mais la façon de le faire est loin d’être claire pour moi. 

edit: variante 4. description

75
Stepan

L'option 5, un pilote de fusion personnalisé, est probablement le moyen de vous rapprocher de ce que vous voulez. C'est étonnamment facile à faire. Vous trouverez ci-dessous un exemple qui, à mon avis, devrait vous rapprocher du comportement que vous désirez.

Commencez par créer un script de pilote de fusion appelé merge-and-verify-driver. Rendez-le exécutable et placez-le à un emplacement approprié (vous pouvez envisager de vérifier ce script dans le référentiel, même si le fichier de configuration du référentiel en dépend). Git va exécuter ce script shell pour fusionner les fichiers sensibles:

#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

Cela ne fait que le comportement de fusion par défaut que Git lui-même fait normalement. La principale différence est que le script renvoie toujours une valeur autre que zéro (pour indiquer qu'il y a eu un conflit, même si la fusion a été résolue sans conflit).

Ensuite, vous devez informer Git de l’existence de votre pilote de fusion personnalisé. Vous faites cela dans le fichier de configuration du référentiel (.git/config):

[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

Dans cet exemple, j'ai mis merge-and-verify-driver dans le répertoire de niveau supérieur du référentiel (./). Vous devrez spécifier le chemin d'accès au script en conséquence.

Maintenant, il vous suffit de donner aux fichiers sensibles les attributs appropriés pour que le pilote de fusion personnalisé soit utilisé lors de la fusion de ces fichiers. Ajoutez ceci à votre fichier .gitattributes:

*.sensitive merge=verify

Ici, j'ai dit à Git que tout fichier dont le nom correspond au modèle *.sensitive devrait utiliser le pilote de fusion personnalisé. De toute évidence, vous devez utiliser un modèle approprié pour votre fichier.

54
Dan Moulding

Remarque: cet article " Ecriture d'un pilote de fusion git pour les fichiers PO " illustre le type de manipulation que vous pouvez effectuer lors de la fusion manuelle d'un fichier: vous pouvez le pré-traiter pour que votre fusion manuelle dispose de certaines données.

git merge-file peut être utilisé, par exemple, pour DÉCRYPTER (et re-chiffrer) des fichiers avant de les fusionner (!)

Dans votre cas, quitter votre pilote de fusion avec un statut différent de 0 garantit que la fusion sera manuelle.

1
VonC

Ces deux commandes semblent avoir le même effet que l'utilisation du pilote de fusion personnalisé: 

git merge --no-commit your_target_branch
git checkout --conflict merge .   (do not forget the . and run it in the top dir of the repository)

La première commande arrête la fusion avant la création du commit de fusion et la seconde marque tous les fichiers modifiés dans les deux branches comme un conflit à résoudre, même s'il n'y avait pas de conflit à l'origine.

0
louisiuol