Travailler sur une branche avec une dépendance sur une autre branche en cours de révision

65

Comment git aide-t-il à gérer le scénario ci-dessous:

J'ai une tâche en deux parties: la tâche principale et la tâche principale. Je fais une demande d'extraction pour fusionner les modifications du backend et j'attends sa fusion (et le retour d'adresse). En attendant, je ne peux pas vraiment travailler sur les modifications du front-end, car cela dépend des modifications apportées au backend et celles-ci ne sont pas encore disponibles sur la branche principale.

Quel est le meilleur moyen d’obtenir les modifications apportées à la branche de modifications frontale à partir de la branche de modifications d’arrière-plan pendant son examen?

sul4bh
la source
14
En règle générale, les interfaces du projet final doivent être clairement définies. Ainsi, lors du démarrage de votre implémentation front-end, cela ne devrait pas vous déranger, si la logique du back-end est toujours revue, car vous pouvez utiliser une maquette.
Herr Derb le
17
@HerrDerb Oh, douce enfant d'été ...
gardenhead
4
Pourquoi ne pouvez-vous pas l'écrire avec votre code de base non encore revu?
user253751
Votre équipe dispose-t-elle d'une technique convenue pour gérer cette situation? Sinon, vous devriez peut-être vous mettre d'accord sur quelque chose comme ça, car c'est une situation assez courante.
Radu Murzea
Il n'y en a pas. C'est la raison pour laquelle j'ai posé cette question. J'ai eu de très bonnes suggestions. Je vais essayer les suggestions et voir comment elles fonctionnent pour moi.
sul4bh

Réponses:

42

J'ai aussi ce problème parfois. Git est très flexible. Voici une façon de le faire.

Votre première branche featureAest en révision.

Votre deuxième branche featureBest en développement et dépend du code de la featureAbranche.

Fusionner la featureAbranche dans la featureBbranche.

Si vous apportez des modifications à la featureAbranche, vous devez à nouveau la fusionner featureAdans la featureBbranche pour intégrer les modifications.

Vous devez également vous assurer de fusionner d'abord featureAdans le coffre principal, sinon, lorsque vous fusionnerez featureBdans le coffre principal, vous fusionnerez également par inadvertance featureA. Une fois que featureAvous avez fusionné avec le coffre principal, vous pouvez vous en débarrasser featureA, car cela featureBne dépend plus que du coffre principal.

Je le préfère lorsque mes branches de fonctionnalités ne dépendent pas les unes des autres, mais parfois et si vous devez les suivre.

Mat
la source
C'est logique. Cela permet-il d'annuler la fusion de featureAsur featureBsi besoin est?
sul4bh
8
Il n'y a pas d'opération d'annulation, mais comme @ 9000 le mentionne, vous pouvez créer une nouvelle branche et sélectionner les commits que vous souhaitez, featureAsi vous deviez recommencer. Il est bon de penser que les branches Git sont jetables. Ils sont économiques et faciles, vous pouvez toujours créer une nouvelle branche. Vous pouvez même créer une branche test hors de votre featureBbranche si vous souhaitez jouer avec quelque chose dont vous n’êtes pas sûr, puis la supprimer si cela ne fonctionne pas ou la fusionner avec votre featureBbranche s’il le faisait.
Matt
9
La fusion créera un désordre qui sera difficile (pas impossible) à annuler. Je choisirais ou rebaisonnerais (c'est-à-dire: tout sélectionner dans featureA à la base de featureB). Voir la réponse de 9000.
Pierre.Sassoulas
1
Cela crée une histoire complexe qui posera problème pendant de nombreuses années à chaque fois que quelqu'un voudra comprendre quel code a été modifié pour featureA et featureB
Ian
2
Si featureA est mis à jour, featureB doit être rebasé et non fusionné
Lyndon White
42

Tenez bon, sautez la fusion

Pour cette approche, vous ne pas vouloir fusionner votre feature_aen feature_bplusieurs reprises.

Le remaniement a été mentionné dans d'autres réponses, mais uniquement pour le rebasement master. Ce que vous voulez faire dans votre cas, c'est:

  • Commencez votre à feature_bpartir de feature_a, à savoir:

    git checkout feature_a
    git checkout -b feature_b
    
  • Chaque fois feature_aque mastervous changez feature_b en attendant d'être fusionné , vous vous basez dessus:

    ... commit something onto feature_a ...
    git checkout feature_b
    git rebase feature_a
    
  • Enfin, feature_aune fois fusionné master, vous obtenez simplement le nouveau masteret vous rebase feature_aune dernière fois:

    git checkout master
    git pull origin master
    git checkout feature_b
    git rebase --onto master feature_a feature_b
    

    Cette dernière rebase va greffer tous les commits qui sont en suspens feature_a(ce qui n’est plus pertinent maintenant car il a été fusionné master) master. Votre feature_best maintenant une simple branche standard allant de master.

EDIT: inspiré des commentaires, un petit avertissement: si vous devez apporter des modifications qui affectent les deux fonctionnalités, veillez à les intégrer feature_a(puis à rebaser comme indiqué). Ne pas le faire dans deux commits différentes dans les deux branches, même si peut être tentant; Comme cela feature_afait partie de l’histoire de feature_b, le fait de changer un seul changement dans deux commits différents sera sémantiquement faux et pourra éventuellement donner lieu à des conflits ou à des "résurrections" de code non désiré, plus tard.

AnoE
la source
2
Si vous vous repositionnez feature_aplusieurs fois, vous risquez par la suite de rencontrer des problèmes, feature_amême s’il a été refondu entre-temps. À la suite de git checkout feature_b; git rebase feature_avotre exécution, vous pouvez avoir des conflits ou des commits amusants contenant des commits qui annulent les nouvelles modifications de feature_a. Cela peut généralement être résolu en utilisant --interactiveet en ignorant les commits pris dans l'ancienne version de l'autre branche (j'ai dû le faire plusieurs fois récemment).
Maaartinus
@ Maaartinus, merci pour le heads-up, je n'ai pas rencontré de tels problèmes moi-même. Comme rebasebeaucoup plus de démarches individuelles qu’une simple merge, il ya sûrement une chance visiblement plus grande de créer des conflits; par contre, il mergeserait tout à fait sémantiquement très faux de le faire dans ce cas.
AnoE
Je suppose que nous mergeaurions des problèmes similaires ou pires (un conflit n’est pas aussi grave que de provoquer un changement indésirable). Je considère une branche comme une séquence de modifications souhaitées précédées de nombreuses modifications indépendantes (appartenant logiquement à une autre branche). Lorsque je modifie à plusieurs reprises avec la même branche, je supprime toujours les modifications non liées car je sais qu'elles entreront de toute façon (éventuellement sous une forme mise à jour) et cela fonctionne bien.
Maaartinus
1
@ Maaartinus, j'ai ajouté un petit addenda à ce sujet (pour apporter systématiquement des modifications qui doivent aller dans les deux branches uniquement dans la branche de base et non dans deux commits différents).
AnoE
Belle technique. C'est comme ça que je le fais toujours aussi. git rebase --ontoFTW: D
Radu Murzea
29

Vous avez déjà une branche dont dépend chacune de vos branches principales et qui ne cesse de changer. Ça s'appelle master.

Pour rester en phase avec une branche de fonctionnalité, le moyen typique masterest de rester au top . Lorsque des mastermodifications sont apportées, vous vous trouvez normalement git fetch origin master:master && git rebase masterdans le répertoire de travail de votre branche.

Vous pouvez faire la même chose avec une autre branche de fonctionnalité: continuez à la récupérer et à la rebaser par-dessus.

Si, pour une raison quelconque, vous devez déplacer vos modifications vers une autre branche, vous pouvez sélectionner vos commits, qui ne sont jamais mélangés avec les commits des autres branches.

9000
la source
Mais je pense que le scénario est que feature-b a besoin du code qui est dans feature-a, la création de branches à partir de master ne sera pas très utile. Où devrais-je commencer? Dois-je passer d'une fonctionnalité-a à une chaîne et les garder synchronisés jusqu'à ce que la fonctionnalité-a soit réintégrée dans master, puis se rebasonner d'une version à une autre?
Sinaesthetic
@Sinaesthetic: vous pouvez bien sûr vous baser feature-bsur feature-a, et faire un rebase à chaque feature-achangement, en fonction de l'évolution. C'est un moyen typique de faire un grand changement observable: divisez-le en part-A(basé sur master), part-B(en fonction part-A), et plus si nécessaire. Faites ensuite une demande de tirage pour chaque partie, et les réviseurs auront plus de facilité à regarder des morceaux plus petits et logiquement groupés.
9000
importera-t-il si je rebase la partie-b avec la partie-a contre la partie-b avec le maître en termes de PR? Je veux juste m'assurer que mes modifications ne montrent pas les modifications de la partie-a comme des modifications dans la partie-b. De plus, si je fusionne contre rebase, comment cela affectera-t-il le PR parti-b? Chaque fois que je pense en comprendre les effets, j'obtiens un résultat différent lol
Sinaesthetic
5

Dans le cas où la tâche frontale a une dépendance critique vis-à-vis du code d’arrière-plan et que vous souhaitez commencer à travailler sur ce dernier avant que celui-ci ne soit finalisé et accepté sur le maître, je démarrerais simplement la tâche en tant que branche de fonctionnalité issue du backend branche, plutôt que de brancher le frontend sur le maître.

Une branche de fonctionnalité qui vit assez longtemps doit fusionner de manière occasionnelle dans les modifications apportées au maître (pour vous assurer de concilier tout conflit de fusion ou sémantique dans le cadre du travail de développement de la branche de fonctionnalité, plutôt que dans le cadre de la révision, de la fusion, de la fusion, etc.). à "maîtriser"). Donc, vous le faites sur votre branche front-end, et lorsque le travail d’arrière-plan a été accepté, vous obtiendrez toutes les modifications mineures qui ont été apportées au back-end dans le cadre de son examen / acceptation automatiquement, par le même itinéraire que celui que vous aviez. obtenir tout autre changement de code sur le maître.

S'il s'avère que la branche dorsale a besoin de beaucoup plus de travail et qu'elle continue à changer sur une période de temps avant d' être fusionnée pour maîtriser (par exemple, si des problèmes majeurs sont détectés lors de la révision), vous voudrez probablement effectuer directement des fusions périodiques. de la branche dorsale à la branche frontale (afin que vous ne continuiez pas à baser tout votre travail frontal sur du code backend obsolète). C'est facile si vous êtes le seul développeur à utiliser les deux fonctionnalités (puisque vous savez si vous apportez vous-même des modifications majeures), mais même si les deux fonctionnalités finissent par être utilisées en parallèle par différents développeurs, tout devrait bien se passer. vous devez simplement rester en communication (ce dont vous auriez besoin de toute façon, si vous travaillez sur des tâches en parallèle où l'une a une dépendance critique à l'autre).

S'il s'avère que toute la branche dorsale doit être abandonnée et ne sera jamais fusionnée (il semblerait que ce serait un accord assez important qui se produirait rarement), vous pouvez alors sélectionner vos modifications dans une nouvelle branche à venir du maître sans le travail d'arrière-plan, ou vous appliquez des validations inverses qui suppriment tout le code d’arrière-plan de la branche frontale. Mais comme je peux le voir, il serait plus probable de suspendre le travail en amont jusqu'à ce que vous sachiez ce qui allait remplacer le backend que vous jetez, puis que vous décidiez quoi faire.

Ben
la source
2

Je ne vois pas le problème ici.

Vous en avez déjà à chaque fois avec votre masterbranche, qui change continuellement pendant que les fonctionnalités sont développées puis fusionnées.

Ainsi, dans votre exemple concret, vous créez d'abord la feature_xxx_backendbranche et développez les modifications d’arrière-plan. Lorsque cela est fait, la branche est prête à réviser et sera fusionnée masterune fois la révision terminée.

Alors, commencez simplement une autre branche, feature_yyy_frontend. Vous voudrez probablement feature_xxx_backendcréer une branche directement à partir de , pour que ces modifications soient déjà dans votre branche. Ensuite, développez simplement la fonctionnalité frontend comme si la branche l’était master.

Lorsque la feature_xxx_backendbranche change, par exemple parce qu’il faut tenir compte de certains points soulevés lors de la révision, faites simplement ces modifications et fusionnez-les dans la feature_yyy_frontendbranche. Continuez ensuite sur la branche frontale.

Une fois la révision de la branche principale terminée, elle est fusionnée master. À ce stade, il serait sage de rebaser la feature_yyy_frontendbranche sur master, de sorte que les réviseurs n’aient besoin que d’examiner les nouvelles modifications apportées par cette branche master, sans avoir à réexaminer les modifications apportées au backend (qui ont déjà été approuvées). )

Cela peut également être fait lorsque vous avez deux, trois ou plusieurs branches dépendantes. Si vous comptez sur deux branches d’entités sur lesquelles vous dépendez, créez simplement une branche dérivée dans laquelle les deux entités sont fusionnées. À partir de là, développez la troisième entité, puis fusionnez les deux en même temps. Lorsque les deux fonctionnalités sont terminées et fusionnées dans la branche dérivée, reposez-vous dessus, ou si elles sont fusionnées dans maître, rebasez-les sur maître.

Le changement de base (comme suggéré ci-dessus) est très puissant et permet de garder un journal clair des modifications, ce qui facilite les révisions.

Polygone
la source
2

Comme Polygnome l'a mentionné, vous pouvez fusionner votre branche frontale avec votre branche backend au lieu des maîtres. Même avec la configuration actuelle de votre branche, vous pouvez simplement faire:

git checkout frontend
git merge backend

ou simplement

git merge backend frontend

Gardez toutefois à l'esprit que si les modifications apportées au back-end ne sont pas acceptées et que davantage de travail est nécessaire, vous devrez fusionner les mises à jour depuis le back-end dans l'interface pour éviter les conflits. Une fois les modifications acceptées dans le maître, vous pouvez redéfinir votre interface sur le maître pour supprimer les commits de fusion d’arrière-plan.

Techniquement, vous pouvez également tout faire avec rebase, mais cela gâchera l’historique des validations de votre branche frontale. D'où je viens, c'est considéré comme une mauvaise pratique. YMMV

Joris Meys
la source
"Bizarre que personne ne dise que vous pouvez réellement fusionner votre branche frontale avec votre branche backend au lieu des maîtres:" Cela a déjà été mentionné, par exemple dans ma propre réponse.
Polygnome
@Polygnome frontend ne doit pas nécessairement être branché directement à partir du backend. Ils peuvent aussi bien être issus du maître, mais vous pouvez toujours les fusionner. Donc, votre réponse ne le mentionne pas réellement.
Joris Meys
En fait, ma réponse ne suggère pas que vous branchez directement depuis le backend, cela signifie simplement que c’est probablement la voie à suivre (étant donné que vous fusionnez de toute façon ces modifications dans la branche frontale).
Polygnome
@ Polygnome alors j'ai mal compris votre réponse. Mis à jour spécialement pour vous :-)
Joris Meys
Je ne sais pas qui a rétrogradé cela, mais dites-moi s'il vous plaît où je me trompe pour que je puisse aussi apprendre quelque chose.
Joris Meys
1

La plupart des réponses ici décrivent correctement le processus de fusion des modifications de la deuxième branche à la première, mais elles n'indiquent pas comment réduire au minimum le nombre de conflits que vous devrez peut-être résoudre.

Lorsque vous souhaitez examiner individuellement deux ensembles de modifications importantes (comme featureAet featureB), créez un PR qui ne doit PAS être fusionné, mais pour recueillir les premières réactions sur une PoC de featureA.

Les gens pourront l'examiner rapidement (il ne s'agit que d'une PoC) et l'objectif est de valider la conception ou l'approche générale.

Ensuite, vous pouvez continuer à travailler sur la fonctionnalité A, créer une demande d'extraction pour celle-ci, créer une branche et travailler sur la fonctionnalité B.

La grande différence est que maintenant vous pouvez vous attendre featureAà ne pas changer radicalement: la conception et l'approche ont déjà été validées. La révision du code et les modifications requises peuvent être subtiles et locales plutôt qu’un «woops, vous avez besoin d’une approche différente». Cela réduira la quantité de travail que vous devez faire pour plus tard fusionner featureBle featureA« code s, quelle que soit la méthode que vous avez choisi.

Alpha
la source