web-dev-qa-db-fra.com

Travailler sur une branche dépendant d'une autre branche en cours de révision

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

J'ai une tâche décomposée en 2 parties: tâche backend et tâche frontend. Je fais une demande d'extraction pour fusionner les modifications du serveur principal et attendre qu'il soit fusionné (et répondre aux commentaires). En attendant, je ne peux pas vraiment travailler sur les changements frontend car cela dépend des changements backend et ceux-ci ne sont pas encore disponibles sur la branche master.

Quelle est la meilleure façon d'extraire les modifications apportées à la branche des modifications du frontend à partir de la branche des changements du backend alors qu'elle est toujours en cours de révision?

79
sul4bh

Attendez, sautez la fusion

Pour cette approche, vous voulez pas vouloir fusionner votre feature_a en feature_b à plusieurs reprises.

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

  • Démarrez votre feature_b de feature_a, c'est à dire.:

    git checkout feature_a
    git checkout -b feature_b
    
  • N'importe quand feature_a change en attendant d'être fusionné dans master, vous rebasefeature_b dessus:

    ... commit something onto feature_a ...
    git checkout feature_b
    git rebase feature_a
    
  • Enfin, dès que feature_a a été fusionné dans master, vous obtenez simplement le nouveau master et le rebase feature_aà ce sujet une dernière fois:

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

    Ce rebase final greffera tous les commits qui pendent du feature_acommit (qui n'est plus pertinent car il a été fusionné dans master) directement sur master. Votre feature_b est maintenant une branche simple et standard allant directement de master.

EDIT: inspiré des commentaires, un peu de tête: si vous avez besoin de faire des changements qui affectent les deux fonctionnalités, alors assurez-vous de le faire dans feature_a (puis rebaser comme indiqué). Faites pas effectuez deux commits différents dans les deux branches, même si cela peut être tentant; comme feature_a fait partie de l'histoire de feature_b, avoir le seul changement dans deux validations différentes sera sémantiquement erroné et pourrait conduire à des conflits ou à des "résurrections" de code indésirable, plus tard.

57
AnoE

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

Votre première branche featureA est en cours d'examen.

Votre deuxième branche featureB est en développement et dépend du code de la branche featureA.

Fusionnez la branche featureA dans la branche featureB.

Si vous apportez des modifications à la branche featureA, vous devez fusionner à nouveau la branche featureA dans la branche featureB pour incorporer les modifications.

Vous devez également vous assurer de fusionner d'abord featureA dans le tronc principal, sinon, lorsque vous fusionnerez featureB dans le tronc principal, vous fusionnerez également par inadvertance featureA. Une fois que featureA est fusionné dans le tronc principal, vous pouvez vous débarrasser de la branche featureA car featureB ne dépend que du tronc principal maintenant.

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

43
Matt

Vous avez déjà une branche dont dépend chaque branche de fonctionnalité et qui ne cesse de changer. Cela s'appelle master.

La manière typique pour une branche de fonctionnalité de rester synchronisée avec master est de rester en haut de celle-ci. Lorsque master change, vous normalement git fetch Origin master:master && git rebase master dans le répertoire de travail de votre branche.

Vous pouvez faire la même chose avec une autre branche de fonctionnalité: continuez à la chercher et à la rebaser dessus.

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

30
9000

Dans ce cas où la tâche frontend a une dépendance critique sur le code backend et que vous souhaitez commencer à travailler sur le frontend avant que le backend ne soit finalisé et accepté sur le maître, je commencerais simplement la tâche frontend en tant que branche de fonctionnalité provenant de la branche backend, plutôt que de brancher le frontend sur master.

Une branche de fonctionnalité qui vit assez longtemps doit fusionner les modifications de master occasionnellement (pour vous assurer de concilier les conflits de fusion ou de sémantique dans le cadre du travail de développement sur la branche de fonctionnalité, plutôt que dans le cadre de la "révision, qa, fusion - "maîtriser"). Donc, vous le faites sur votre branche frontale, et lorsque le travail du backend a été accepté à maîtriser, vous obtiendrez toutes les modifications mineures qui ont été apportées au backend dans le cadre de son examen/acceptation automatiquement, par le même chemin que vous auriez obtenir toutes les autres modifications de code sur le maître.

S'il s'avère que la branche backend a besoin de beaucoup plus de travail et qu'elle continue de changer au fil du temps avant fusionné avec le maître (par exemple, si des problèmes majeurs sont détectés lors de la révision), alors vous vous feriez voulez probablement faire des fusions périodiques directement de la branche backend dans la branche frontend (donc vous ne continuez pas à baser tout votre travail frontend sur du code backend obsolète). C'est facile si vous êtes le seul développeur à faire les deux fonctionnalités (puisque vous savez si vous faites vous-même des changements majeurs), mais même si les deux fonctionnalités finissent par être travaillées en parallèle par différents développeurs, cela devrait aller; il vous suffit de rester en communication (ce dont vous auriez besoin de toute façon, si vous travaillez en parallèle sur des tâches où l'une a une dépendance critique avec l'autre).

S'il s'avère que toute la branche back-end doit être abandonnée et ne sera jamais fusionnée (il semble que ce soit une affaire assez importante qui se produirait rarement), alors vous pouvez choisir vos engagements dans une nouvelle branche venant du maître sans le travail backend, ou vous appliquez des validations inverses qui suppriment tout le code backend à la branche frontend. Mais comme je peux le voir, il serait plus probable de suspendre le travail frontal jusqu'à ce que vous trouviez ce qui allait remplacer le backend que vous jetez, puis décidiez quoi faire.

5
Ben

Je ne vois pas le problème ici.

Vous l'avez déjà à chaque fois avec votre branche master, qui ne cesse de changer pendant que les fonctionnalités sont développées puis fusionnées.

Donc, dans votre exemple concret, vous créez d'abord le feature_xxx_backend branche et développe les modifications du backend. Lorsque cela est fait, la branche est à réviser et sera fusionnée dans master une fois la révision terminée.

Alors, démarrez simplement une autre branche, feature_yyy_frontend. Vous souhaiterez probablement vous connecter directement à partir de feature_xxx_backend, afin que vous ayez déjà ces changements dans votre branc. puis développez simplement la fonction frontend si la branche était master.

Quand le feature_xxx_backend changements de branche, par ex. car il y a des choses qui surviennent lors de la révision qui doivent être traitées, il suffit de faire ces changements et de les fusionner dans le feature_yyy_frontend branche. Continuez ensuite sur la branche frontend.

Une fois la révision de la branche backend terminée, elle est fusionnée dans master. À ce stade, il serait sage de rebaser le feature_yyy_frontend branchez sur master, de sorte que les réviseurs doivent seulement examiner les nouveaux changements auxquels cette branche contribue master, et pas besoin de revoir les modifications apportées au backend (qui ont déjà été approuvées).

Cela peut également être fait lorsque vous avez deux, trois branches dépendantes ou plus. Si vous avez deux branches d'entités dont vous dépendez, créez simplement une branche dérivée qui a fusionné les deux entités. À partir de là, développez la troisième entité, fusionnez les deux branches d'entités en cours de route lorsque chacune d'elles change. Lorsque les deux fonctionnalités sont terminées et fusionnées dans la branche dérivée, rebasez dessus, ou si elles sont fusionnées dans master, rebasez sur master.

Rebasing (comme suggéré ci-dessus) est vraiment puissant et aide à garder un journal propre des changements, ce qui facilite les révisions.

2
Polygnome

Comme Polygnome l'a mentionné, vous pouvez réellement fusionner votre branche frontend avec votre branche backend au lieu des masters. Même avec la configuration de branche actuelle que vous avez maintenant, vous pouvez simplement faire:

git checkout frontend
git merge backend

ou simplement

git merge backend frontend

Gardez à l'esprit que si les modifications du backend ne sont pas acceptées et que davantage de travail est nécessaire, vous devrez fusionner les mises à jour du backend dans le frontend pour éviter les conflits. Une fois les modifications acceptées dans le maître, vous pouvez rebaser votre frontend sur le maître pour vous débarrasser des commits de fusion du backend.

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

2
Joris Meys

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'abordent pas la façon de minimiser le nombre de conflits que vous devrez peut-être résoudre.

Chaque fois que vous avez deux ensembles de modifications importantes que vous souhaitez examiner individuellement (comme featureA et featureB), créez un PR qui n'est PAS censé être fusionné, mais pour recueillir des commentaires précoces sur un PoC de featureA.

Les gens pourront l'examiner rapidement (c'est juste un 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 et créer une branche et travailler sur la fonctionnalité B.

La grande différence est que vous pouvez désormais vous attendre à ce que featureA ne change pas 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 que "woops, vous avez besoin d'une approche différente". Cela minimisera la quantité de travail que vous devrez faire pour fusionner plus tard featureB sur le code de featureA, quelle que soit la méthode choisie.

1
Alpha