76 votes

git fusion partielle, pas la branche entière

J'ai lu des articles sur des astuces avec la fusion dans Git : fusionner les branches publiques et privées tout en gardant certains fichiers intacts dans les deux branches et d'autres et n'ont pas trouvé de solution.

Dans mon cas, je ressens le besoin de faire une stratégie de fusion opposée. Dans le cadre d'un développement parallèle, je dois garder certains fichiers identiques entre les branches arbitraires. De l'autre côté, je ne veux pas faire de fusion de type squash ou no-commit, alors que les différences sont significatives et pourraient casser l'état actuel de la branche de test.

Ce que je veux, c'est quelque chose comme

git checkout testing

git merge config.xml -b development o git merge config\*.xml -b development

Je suppose que c'est comme git merge-files ... mais le deuxième fichier provient de la branche et non du système de fichiers. Est-ce possible ? ou peut-être y a-t-il une sorte de solution de contournement ? des submodules ? des attributs ?

Merci

1 votes

2 votes

Le choix des cerises créera un commit dupliqué, et sur la route cela peut causer des conflits de fusion excessifs, ou pire encore, aucun conflit et le mauvais code est pris. Le commentaire de @Vadzim est un lien vers la bonne réponse si vous voulez faire de vraies fusions partielles qui permettront à vos branches de se réconcilier correctement lorsque des doubles choisis se rencontrent. Ce lien renvoie à un article de blog en 10 parties que vous devrez probablement lire deux fois avant qu'il n'ait un sens, mais qui en vaut la peine si vous voulez vraiment comprendre la fusion git.

70voto

mipadi Points 135410

Il y a plusieurs choses que vous pouvez faire.

Premièrement, vous pouvez cueillir des cerises les changements que vous voulez, ce qui n'applique qu'un seul commit. Par exemple, s'il y a un changement qui ne touche qu'à config.xml vous pouvez l'extraire avec

$ git cherry-pick $COMMIT_ID_YOU_WANT

Vous pouvez aussi simplement prendre config.xml de la branche de développement :

$ git checkout testing
$ git checkout development -- config.xml

Cela vous donnera la même version de config.xml qui existe dans la branche de développement, mais notez qu'il n'y aura pas d'historique des modifications du fichier.

0 votes

C'est ce que je cherche. Merci. Un seul souhait encore, ce serait du luxe si je pouvais écrire git cherry-pick $COMMIT_ID config.xml. Ok, c'est un souhait pour le forum git.

11 votes

Pour la deuxième solution : Cela provoquerait-il un conflit de fusion si la branche de test était fusionnée avec la branche de développement ? J'ai une situation où je veux apporter les changements d'une branche de fonctionnalité à une autre, et je ne suis pas sûr que ce soit une bonne idée parce que lorsque les deux branches fusionnent vers le master, cela pourrait causer un grand nombre de conflits...

0 votes

Le -- dans le développement de git checkout -- config.xml est-il nécessaire ?

24voto

lumpidu Points 321

En gros, vous pouvez tous lire après ici : http://www.gelato.unsw.edu.au/archives/git/0701/37964.html

En bref, si vous voulez juste appliquer les changements faits par une certaine gamme de commits (cela peut aussi bien être un seul commit), faits à seulement un sous-ensemble de fichiers alors faites-le :

git diff commit1..commit2 filepattern | git apply --index && git commit

14voto

BimbaLaszlo Points 324

Voici un référentiel avec une documentation étape par étape pour clarifier les dangers de la fusion partielle et montrer le bon chemin.

https://gitlab.com/bimlas/learning-by-testing-git-partial-merge/tree/doc

TL;DR :

La fusion doit être ce qu'elle est : une union de branches. Si vous faites un commit de fusion sans fusionner tous les fichiers, et que vous essayez de fusionner les mêmes branches plus tard, alors Git pense que vous avez tout fusionné dans le premier commit de fusion, donc les commits précédents n'ont pas d'importance, il ignorera les changements non fusionnés avant la première fusion.

Utilice checkout pour copier des fichiers d'une branche à l'autre :

git checkout BRANCH -- FILE
git commit -m "Partial merge"

6voto

Hugues Points 11

Il est possible de fusionner avec un fichier directement prélevé dans l'arborescence git.
Ce que je suggère est de faire quelque chose comme :
$ git ls-tree development -- config.xml $ git show <blob-hash> > config.xml.development

On obtient alors la base commune :

$ git ls-tree $(git merge-base HEAD development) -- config.xml $ git show <blob-hash> > config.xml.base

Et enfin :

$ git merge-file config.xml config.xml.base config.xml.development

Je ne l'ai pas testé, cependant.

Avec un shell comme zsh, vous pouvez éviter de sauvegarder le blob dans un fichier temporaire avec ce :

$ git merge-file config.xml =(git show <base-blob-hash>) =(git show <dev-blob-hash>)

1 votes

En bash, vous pourriez faire : $ git merge-file config.xml $(git show <base-blob-hash>) $(git show <dev-blob-hash>)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X