Ecraser une branche par une autre avec Git

Logo du SCM GITDans le cycle de vie d’une application, il arrive parfois qu’une branche prenne le pas sur une autre  branche et qu’il soit nécessaire d’écraser la seconde par la première. Prenons l’exemple d’une application où, par convention, le master (ou le trunk sous SVN) est considéré comme la branche de développement (axée vers le futur) et que l’utilisation du système de branches soit habituellement consacrée aux branches de maintenance. Dans certaines circonstances (ex : nouveaux développements à commencer pour la version N+2, migration technique à réaliser …), une branche peut prendre le dessus du master. Afin de retrouver la convention d’origine, une recopie de la branche sur le master va, à termes, être nécessaire. Que ce soit avec Git ou git-svn, nous allons voir comment Git peut nous y aider en quelques lignes de commande.

Mise en scène

L’historique de commits ci-dessous illustre les explications qui suivront :
Historique des commits réalisés avec Git

Cet historique des commits commence par la branche master sur laquelle les fonctionnalités A et B ont été commitées. La branche maBranche est alors créée à partir du commit de la fonctionnalité B. Un premier merge no fast-forward est créé pour récupérer la fonctionnalité E de master dans maBranche : le commit de merge « Merge branch ‘master’ into maBranche » est créé.

A partir de là, les nouvelles fonctionnalités F, G et H sont développées sur maBranche. Ne pouvant attendre la fin des développements de la fonctionnalité G qui résoudrait proprement le problème rencontré par les utilisateurs, est créé sur le master un contournement permettant d’y palier temporairement. Ce Hotfix est déployé en production. N’ayant aucun intérêt dans les prochaines versions de l’application, ce Hotfix ne doit être en aucun cas mergé sur maBranche. Une fois les développements de la fonctionnalité H terminés et déployés en production, l’équipe décide de faire revenir sur le master les développements de maBranche.
Les 2 derniers commits de l’historique mettent en œuvre cette opération.

Commandes

Voici les 4 lignes de commandes à exécuter pour réaliser cet écrasement de branche :

  1. Se placer sur la branche à conserver
    git checkout maBranche
  2. Demander une fusion avec la stratégie ours (attention, ceci est différent d’un merge avec stratégie recursive et l’option ours) qui va uniquement conserver le contenu de la branche actuelle. En effet, l’option -s ours indique à Git de fusionner la branche source dans la branche cible mais sans aucunement modifier la branche cible. Cette stratégie est habituellement utilisée pour ne pas reporter un commit d’une branche de maintenance sur le master.
    git merge -s ours master -m « Merge avec stratégie ours »
  3. Repasser sur la branche master
    git checkout master
  4. Demander une fusion de la branche maBranche vers le master tout en conservant 2 branches distinctes (un fast-forward aurait été réalisé puisque que le dernier commit n’est autre que notre fusion de la commande n°2).
    git merge –no-ff maBranche

Sortie console sur notre exemple de la commande Git n°4 :
Log du git merge --no-ff maBranche

Comme attendu, le fichier Hotfix.txt ayant été ajouté lors du commit Hotfix est supprimé du master. Si, dans un autre exemple, le commit Hotfix avait modifié une ligne du fichier FeatureE.txt, un revert de cette modification aurait alors été effectué.

Conclusion

Cet article explique comment Git permet d’écraser le contenu de la branche A par une branche B lorsque la branche B a pris le pas sur la branche A et qu’aucune des modifications présente dans le branche A n’a besoin d’être conservée (tout a été préalablement fusionné, reporté par cherry-pick, copié à la main ou volontairement ignoré car à ne pas reporter).
Cerise sur le gâteau : ces opérations sont applicables entre 2 branches SVN par le biais du bridge git-svn.

Une réflexion au sujet de « Ecraser une branche par une autre avec Git »

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *