web-dev-qa-db-fra.com

Comment aborder une fusion compliquée

Voici l'affaire, j'ai rejoint une nouvelle entreprise et on m'a demandé de terminer le travail sur une branche qui n'a pas été touchée depuis près d'un an. Pendant ce temps, la branche master progresse à un rythme soutenu. Idéalement, je voudrais fusionner toutes les modifications de la branche principale dans la branche des fonctionnalités et continuer le travail à partir de là, mais je ne sais pas trop comment aborder cela.

Comment effectuer cette fusion en toute sécurité tout en préservant les modifications importantes des deux côtés de la branche?

28
Vlad Spreys

Au fond, comment combiner deux morceaux de code (éventuellement non compatibles) est un problème problème de développement, et non contrôle de version. La commande Git merge peut aider dans ce processus, mais cela dépend de la forme du problème.

La comparaison des deux versions avec la base est la plus logique. Cela vous donnera une idée de la meilleure stratégie pour aller de l'avant. Votre approche peut être différente en fonction de la nature et du chevauchement des changements dans chaque branche.

Imaginez le scénario idéal: vous découvrirez que la branche principale et la branche de fonctionnalité ne modifient chacune que des parties mutuellement exclusives du code, de sorte que vous pouvez simplement valider toutes les modifications et être prêt à partir.

Bien sûr, ce ne sera certainement pas le cas, mais la question est: jusqu'où sera-t-il éloigné de ce scénario idéal? c'est-à-dire à quel point les changements sont-ils entremêlés?

En outre, quelle était la maturité de l'ancienne branche de fonctionnalité? Était-il en bon état de fonctionnement ou non (ou inconnu)? Quelle partie de la fonctionnalité a été terminée?

Si le code pertinent dans la branche principale a beaucoup changé au cours de la dernière année, ou si la fonctionnalité n'est pas dans un état très mature, je pourrais envisagez de créer une nouvelle fourchette de la dernière et d'incorporer manuellement l'ancienne fonctionnalité à nouveau . Cela vous permettra d'adopter une approche incrémentielle pour le faire fonctionner.

Si vous faites une fusion désordonnée de beaucoup de code et que cela ne fonctionne pas, il sera assez difficile à déboguer. Si la branche principale a beaucoup changé au cours de la dernière année, des changements de conception majeurs peuvent être nécessaire à la fonctionnalité pour la faire fonctionner. Il ne serait pas approprié d'apporter ces modifications via "résoudre les conflits", car cela nécessiterait d'effectuer toutes les modifications en même temps et en espérant que cela fonctionne. Ce problème serait aggravé par la possibilité de bogues dans l'ancienne branche partiellement terminée.

28
user82096

Dans mon expérience limitée de Git, je peux dire qu'il est parfois plus rapide de redémarrer la branche de fonctionnalité si le maître est allé trop loin du point de détachement.

Fusionner deux branches sans connaître l'historique du code (étant donné que vous venez de rejoindre le projet) est vraiment difficile, et je parie que même un développeur qui a suivi le projet depuis le début ferait probablement des erreurs dans la fusion.

Bien sûr, cela a du sens si la branche de fonctionnalité n'est pas énorme, mais vous pouvez simplement garder l'ancienne branche de fonctionnalité ouverte, branche à nouvea du maître et manuellement introduire des changements qui composent cette fonctionnalité. Je sais que c'est l'approche la plus manuelle, mais elle vous permet d'être en contrôle total en cas de code manquant ou déplacé.

La programmation en binôme avec un senior dans ce cas serait le meilleur des cas, vous aidant à mieux connaître le code.
Cela pourrait même s'avérer plus rapide aussi, si vous prenez en compte les conflits de fusion et le temps de test!

Je suppose en quelque sorte qu'au moins essayer de faire une fusion est évidemment la meilleure chose à faire. Si cela échoue ou s'avère trop difficile, essayez la cueillette des cerises, si cela ne fonctionne pas, suivez la méthode manuelle.

24
GavinoGrifoni

git-imerge est conçu exactement à cet effet. C'est un outil git qui fournit une méthode de fusion incrémentielle . En fusionnant de manière incrémentielle, il vous suffit de gérer les collisions entre deux versions, jamais plus. En outre, un nombre beaucoup plus important de fusions peut être effectué automatiquement car les ensembles de modifications individuels sont plus petits.

17
Joe

Essayer de fusionner la tête principale sur une branche rassis de l'année peut être un exercice de frustrations et d'approfondir la bosselure sur le bureau avec votre front.

La ligne principale n'est pas arrivée à sa place en une seule fois au cours des mois. Il avait également du développement et des versions. Essayer de tout mettre à jour en une seule fusion monolithique peut être écrasant.

Au lieu de cela, commencez par fusionner de la première fonctionnalité à la fusion avec la ligne principale après la division de la branche périmée. Obtenez que fusionne en travaillant. Ensuite, la fonctionnalité suivante fusionne. Etc. Beaucoup de ces fonctionnalités fusionneront sans conflit. Il est toujours important de s'assurer que la fonctionnalité actuelle de la branche périmée reste compatible avec la direction dans laquelle la ligne principale a disparu.

Vous souhaiterez peut-être dériver du chef de la branche périmée pour le rôle de la fusion dans d'autres changements. Il s'agit davantage de s'assurer que les validations et l'historique lorsque quelqu'un y repense sont clairs et communiquent quel est le rôle et la politique de chaque branche. La branche périmée était une branche caractéristique. Celui à partir duquel vous travaillez est une branche d'accumulation et de réconciliation.

Une grande partie de cela sera plus facile si les anciennes branches de fonctionnalités ou de versions existent toujours et sont facilement accessibles (certains endroits ont une politique de nettoyage des noms des branches plus anciennes que certaines dates afin que la liste des branches ne soit pas écrasante ).

L'important dans tout cela est de s'assurer que vous testez et corrigez après avoir fusionné avec succès chaque partie de l'historique de la ligne principale. Même si quelque chose peut fusionner sans conflits, cela signifie simplement que le code n'est pas en conflit. Si le mode d'accès à la fonction périmée a été déprécié ou supprimé, il peut être nécessaire de corriger une fusion réussie.

En passant, cela fonctionne également pour d'autres systèmes de contrôle de version. J'ai parfois eu besoin de fusionner un groupe spécifique de validations svn dans une branche (sélection de cerise) pour une fonctionnalité, de corriger la branche pour qu'elle fonctionne avec cette fonctionnalité, puis de fusionner le groupe suivant de validations svn plutôt que de simplement faire un svn en gros fusionner.

Alors que l'un peut faire un choix de cerise git ici, et cela permet d'apporter spécifique commits, cela présente certains inconvénients qui peuvent compliquer le processus. La cerise sur le gâteau n'affichera pas d'informations sur le commit que vous avez choisi (vous pouvez l'ajouter au message de commit). Cela rend plus difficile le suivi des commits dans l'histoire.

En outre, cela signifie que vous n'allez pas rejouer efficacement le maître sur la branche périmée - vous allez choisir des fonctionnalités éventuellement incomplètes - et ces fonctionnalités peuvent être lues dans le désordre.

La principale raison pour laquelle on devrait fusionner des validations historiques à maîtriser sur la branche périmée est de pouvoir conserver le, appelons-le "histoire future" de la branche rassis dans un état que vous pouvez raisonner. Vous pouvez clairement voir les fusions de l'historique sur la branche périmée et les correctifs pour réintégrer la fonctionnalité. Les fonctionnalités sont ajoutées dans le même ordre qu'elles devaient être maîtrisées. Et quand vous avez terminé, et enfin faire la fusion du chef de maître sur la branche périmée, vous savez que tout a été fusionné et vous ne manquez aucun commit.

6
user40980

Étape 1. Découvrez le code, analysez son architecture et les modifications apportées aux deux branches depuis le dernier ancêtre commun.

Étape 2. Si la fonctionnalité semble largement indépendante et touche principalement différents domaines de code, fusionnez, résolvez les conflits, testez, corrigez, etc. Sinon, passez à l'étape 3

Étape 3. Analysez les zones de conflit, comprenez l'impact fonctionnel et les raisons en détail. Il pourrait facilement y avoir des conflits dans les exigences commerciales qui apparaissent ici. Discutez avec les BA, les autres développeurs, le cas échéant. Découvrez la complexité de la résolution de l'interférence.

Étape 4. À la lumière de ce qui précède, décidez si vous souhaitez fusionner/sélectionner/même couper-coller uniquement les parties qui n'entrent pas en conflit et réécrire les pièces en conflit, OR si pour réécrire toute la fonctionnalité à partir de zéro.

1
Brad Thomas

1. Basculez vers la branche qui est utilisée comme principale branche développeur/version.

Il s'agit de la branche qui contient les dernières modifications apportées au système. Peut être master, core, dev, cela dépend de l'entreprise. Dans votre cas, c'est probablement master directement.

git checkout master
git pull

Tirez pour vous assurer que vous avez acquis la dernière version de la branche principale de développement.

2. Checkout et tirez sur la branche qui contient le travail que vous êtes censé terminer.

Vous tirez pour vous assurer que vous disposez bien du dernier contenu de la branche. En le vérifiant directement, sans le créer localement au préalable, vous vous assurez de ne pas y avoir le nouveau contenu de master (ou de la branche principale de développement).

git checkout <name of the obsolete branch>
git pull Origin <name of the obsolete branch>

. Fusionnez la branche principale de développement à la branche obsolète.

Avant d'exécuter la commande suivante, assurez-vous, soit en tapant git branch Ou git status Que vous êtes sur la branche obsolète.

git merge master

La commande git merge Essaiera de fusionner le contenu de la branche spécifiée, dans ce cas master, avec la branche dans laquelle vous vous trouvez actuellement.

Accent sur va essayer. Il peut y avoir des conflits de fusion, qui devront être résolus par vous et par vous seul.

4. Fixez les conflits de fusion, validez et poussez le correctif de conflit

Après avoir corrigé le conflit de fusion dans tous les fichiers où il y en a, mettez en scène, validez et poussez la résolution du conflit vers Origin.

git add .
git commit -m "fixed the merge conflict from the past year to update the branch"
git Push

Vous pouvez généralement appeler git add . Pour mettre en scène tous les fichiers à valider. Lorsque vous traitez des conflits de fusion, vous souhaitez que tous les fichiers nécessaires soient mis à jour.

Remarque additionnelle

La résolution des conflits de fusion peut être un travail fastidieux. Surtout si vous êtes nouveau dans une entreprise. Vous n'avez peut-être même pas encore les connaissances nécessaires pour résoudre tous les conflits de fusion.

Prenez le temps d'inspecter attentivement tous les conflits qui se sont produits et de les corriger de manière appropriée, avant de poursuivre votre travail.


Cela peut arriver, vous commencez à travailler sur une branche vieille d'un an, vous y fusionnez l'état de développement actuel et vous n'aurez aucun conflit de fusion.

Cela se produit lorsque même si le système a beaucoup changé au cours de l'année, personne n'a touché les fichiers qui ont été modifiés dans la branche d'un an.

0
Andy