Stratégie de révision du code avant la fusion vers le master des branches de fonctionnalités


22

Mon équipe et moi utilisons des branches de fonctionnalités (avec git). Je me demande quelle est la meilleure stratégie de révision de code avant de fusionner pour maîtriser.

  1. Je vérifie une nouvelle branche du maître, appelons-la fb_ # 1
  2. Je m'engage plusieurs fois et que je veux le fusionner de nouveau pour le maîtriser
  3. Avant de fusionner, quelqu'un est censé faire une révision de code

Il y a maintenant 2 possibilités:

1er

  1. Je fusionne master à fb_ # 1 ( pas fb_ # 1 à master) pour le rendre le plus à jour possible
  2. Un coéquipier examine les changements entre la tête principale et la tête fb_ # 1
  3. Si fb_ # 1 est ok on fusionne fb_ # 1 pour master
  4. Avantages: aucun code obsolète en revue
  5. Inconvénients: si quelqu'un d'autre fusionne quelque chose entre "1". et "2." ses modifications apparaissent dans la revue, bien qu'elles appartiennent à une autre revue.

2e

  1. Un coéquipier examine les changements entre le point de paiement (git merge-base master fb_ # 1) et fb_ # 1 head
  2. Avantages: nous voyons exactement ce qui a été changé pendant le travail sur la branche de fonctionnalité
  3. Inconvénients: du code obsolète peut apparaître dans la revue.

Quelle manière pensez-vous est la meilleure et pourquoi ? Peut-être existe-t-il une autre approche plus appropriée?

Réponses:


9

Il y a une variation de votre 1ère option:

  1. fusionner le maître vers fb_ # 1 (pas fb_ # 1 vers le maître) pour le rendre le plus à jour possible
  2. Un coéquipier examine les changements entre le maître au point de fusion et la tête fb_ # 1
  3. Si fb_ # 1 est ok on fusionne fb_ # 1 pour master
  4. vérification rapide que la fusion est correcte

par exemple.

... ma -- ... -- mm -- ... -- mf  <- master
      \            \         /
       f1 ... fn -- fm -----      <-- fb_#1

où:

  • ma est l'ancêtre de master et fb_ # 1.
  • fn est le dernier changement de votre branche
  • mm est le commit qui était master / HEAD au moment où vous avez fusionné sur votre branche (donnant fm ).

Donc, vous comparez mm et fm dans votre examen initial, puis vérifiez rapidement après la fusion de mf pour vous assurer que rien de significatif n'a changé sur le maître lors des étapes 1 à 3. Cela semble avoir tous les avantages et aucun inconvénient pour l'examen initial.

Cela suppose que l'examen est rapide par rapport à la fréquence normale des changements poussés vers le master, donc fm -> mf serait souvent une avance rapide.

Si ce n'est pas le cas, pour quelque raison que ce soit, les inconvénients passeront simplement de l'examen initial à l'examen post-fusion, et il peut être plus simple de fusionner directement sur le maître et de faire un seul examen là-bas.


Comment obtenir "le point que vous avez fusionné"? Est-ce que "git merge-base master head" sera correct, ou affichera-t-il le point de branchement initial?
Andrzej Gis

À moins que vous ne mettiez délibérément à jour master après la fusion, ce sera juste master.
inutile

Oui, mais comment obtenir ce point si quelqu'un d'autre le met à jour?
Andrzej Gis

Lorsque vous êtes sur la branche fb, utilisez git show HEAD. Comme ce sera le fm commit de fusion , il listera les deux parents. Donc, vous avez le hachage de mm . Alternativement, vous pouvez voir trivialement le parent dans gitkou tout autre navigateur git
Inutile

13

3e

  • Vous rebasez la branche sur le maître pour la mettre à jour et garder les modifications séparées.

    Cela crée une nouvelle histoire de la branche. Ce seront de nouvelles révisions avec de nouveaux ID qui auront le même contenu, mais qui seront dérivées du dernier maître et ne seront pas liées aux anciennes révisions. Les anciennes révisions sont toujours accessibles dans "reflog" si vous devez vous y référer, par exemple parce que vous trouvez que vous avez fait une erreur dans la résolution des conflits. En plus de cela, ils ne valent rien. Git taille par défaut le reflog après 3 mois et supprime les anciennes révisions.

  • Vous utilisez un rebase interactif ( git rebase -ietgit commit --amend ) pour réorganiser, modifier et nettoyer les modifications afin que chacune effectue une modification fermée logiquement.

    Cela crée à nouveau un nouvel historique, cette fois avec l'avantage supplémentaire que vous pouvez restructurer les modifications pour les rendre plus pertinentes pendant la révision.

  • Avantages:

    • aucun code obsolète en revue
    • nous voyons exactement ce qui a été changé pendant le travail sur la branche de fonctionnalité
  • Les inconvénients:
    • un peu plus de travail
    • vous devez prendre soin de ne pas rebaser tout ce qui est déjà fusionné ou que vous avez partagé et le destinataire ne s'attend pas à ce qu'il soit rembobiné.

Habituellement, le travail supplémentaire signifie que vous passez d'abord en revue le code vous-même, ce qui entraînera également de nombreux problèmes.

C'est ce que font Linux et Git. Et il n'est pas rare de voir des séries de 20 à 25 correctifs soumis pour examen et réécrits plusieurs fois dans ces projets.

En fait, Linux l'a fait dès le début du projet lorsque leur contrôle de version préféré était des tarballs et des correctifs. Lorsque de nombreuses années plus tard, Linus a décidé de créer git, c'était la principale raison de la mise en œuvre de la rebasecommande et de sa variante interactive. De plus, git a une notion distincte d' auteur et de committer . L'auteur est celui qui a créé la révision en premier et le committer est celui qui l'a touchée en dernier. Étant donné que sous Linux et Git, les correctifs sont toujours envoyés par e-mail, les deux ne sont presque jamais la même personne.


1
+1 également, l'OP n'a pas posé de questions sur les prochaines étapes, mais pour obtenir votre fonctionnalité dans master, vous pouvez utiliser une merge --no-ffqui montrera clairement que la branche sur master au lieu de la fonctionnalité disparaît simplement dans le reste des
validations

@stijn: --no-ffa ses avantages et ses inconvénients. Personnellement, je trouve ça plus de bruit qu'autre chose. YMMV.
Jan Hudec

ouais c'est une question de préférence .. Si le maître est normalement propre et droit, cela ne me dérange pas que les grandes fonctionnalités aient une "bulle" séparée. Si le maître est déjà un gâchis, no-ff ne fait qu'empirer les choses
stijn

J'aimerais pouvoir accepter le mode d'une seule réponse. Une solution hybride serait idéale. Utiliser rebase et comparer avec le point de branchement semble être la meilleure façon de procéder.
Andrzej Gis

Second Con - Je ne pense pas que vous puissiez le faire si vous avez déjà partagé votre branche avec quelqu'un. Lorsque vous réécrivez l'historique, il y aura des incohérences.
sixtyfootersdude

4

Il y a en fait une troisième possibilité - et probablement beaucoup d'autres, car GIT est plus une implémentation d'un cadre SCM qu'une implémentation d'une méthodologie SCM. Cette troisième possibilité est basée sur rebase.

La rebasesous-commande GIT prend une série de validations (généralement de votre point de branchement à la pointe de votre branche de sujet topic) et les rejoue ailleurs (généralement à la pointe de votre branche d'intégration, par exemple master). La rebasesous-commande génère de nouveaux validations, ce qui donne la possibilité de réorganiser les validations sous une forme plus facile à examiner. Cela donne une nouvelle série de commit, similaire à ce qui était topicauparavant mais apparaissant enraciné en haut de la branche d'intégration. Cette nouvelle branche est toujours appelée topicpar GIT, de sorte que l'ancienne référence est supprimée. J'étiquette de manière informelle topic-0l'état d'origine de votre agence topic-1et ainsi de suite ses différents refactoring.

Voici ma suggestion pour votre topicbranche:

  1. (Étape facultative) Vous rebasez de manière interactive votre branche de sujet topicsur son point de branchement (voir l' --fixupoption pour commitet les options -iet --autosquashsur rebase), ce qui vous donne la possibilité de réécrire vos validations d'une manière plus facile à réviser. Il en résulte une branche topic-1.

  2. Vous rebasez votre branche de sujet en haut de votre branche d'intégration, c'est comme faire une fusion, mais «ne pollue pas» l'histoire avec une fusion qui n'est qu'un artefact d'ingénierie logicielle. Il en résulte une branche topic-2.

  3. Envoyer topic-2à un coéquipier qui l'examine contre la pointe de master.

  4. Si tout topic-2va bien, fusionnez-le avec master.

REMARQUE Les branches - où branche fait référence à l'arbre de validation - seront toutes appelées de la même manière par GIT. Ainsi, à la fin du processus, seule la branche topic-2a un nom dans GIT.

Avantages:

  • Aucun code obsolète en revue.
  • Pas de fausses critiques sur les «fusions étrangères» (le phénomène que vous avez décrit au 1er).
  • Possibilité de réécrire les commits d'une manière propre.

Les inconvénients:

  • Au lieu d'une branche topic-0, il y a trois branches artefacts topic-0, topic-1et topic-2qui sont créés dans le commettras arbre. (Bien qu'à tout moment, un seul d'entre eux ait un nom dans GIT.)

Dans votre 1er scénario «si quelqu'un a fusionné quelque chose entre« 1 ». et "2." »fait référence au temps qui s'écoule entre la création du point de branchement et le moment où vous décidez de fusionner. Dans ce scénario «si quelqu'un a fusionné quelque chose entre« 1 ». et "2." »se réfère à l'intervalle de temps entre le rebase et la fusion, qui est généralement très court. Ainsi dans le scénario que je propose, vous pouvez «verrouiller» lemaster branche pour le temps de la fusion sans perturber significativement votre workflow, alors que cela n'est pas pratique dans le 1er scénario.

Si vous faites des revues de code systématiques, c'est probablement une bonne idée de réorganiser les commits de manière adéquate (étape facultative).

La gestion des artefacts de branche intermédiaire ne présente une difficulté que si vous les partagez entre les référentiels.


Il ne faut pas topic-0, topic-1et les topic-2branches. A la seconde où le rebase est terminé, la version précédente n'a plus d'importance. Donc , tout ce qu'il y aurait est topic@{1}, topic@{2}, topic@{yesterday}, topic@{3.days.ago}etc. pour sauver vos fesses si vous trouvez que vous déconné la résolution des conflits dans le rebasage.
Jan Hudec

Les trois branches existent, mais n'ont pas de nom (pas de réf). Je devrais peut-être le souligner.
Michael Le Barbier Grünewald

Les révisions existent et sont signalées par des entrées de reflog. Mais comme branches il y a juste un, topic. Parce que branch in git n'est que le nom.
Jan Hudec

Comment cela me sauve-t-il des «fusions étrangères»? Que se passe-t-il si quelqu'un fusionne avec le maître après avoir envoyé le sujet-2 à un coéquipier et que le coéquipier l'examine par rapport au conseil du maître?
Andrzej Gis

@JanHudec A tout moment, il n'y a qu'une seule branche appelée topicI étiquetée dans GIT, il est toujours l' une des branches (une branche comme COMMIT arbre, pas comme référence GIT) topic-0, topic-1, topic-2.
Michael Le Barbier Grünewald
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.