Mon bureau veut une fusion infinie de branches en tant que politique; Quelles autres options avons-nous?

119

Mon bureau essaie de comprendre comment nous gérons les scissions et les fusions de succursales, et nous avons un gros problème.

Notre problème concerne les branches secondaires à long terme - du genre où vous avez quelques personnes qui travaillent dans une branche qui se sépare de master, nous développons pendant quelques mois et lorsque nous atteignons un jalon, nous synchronisons les deux.

Maintenant, à mon humble avis, la façon naturelle de gérer cela est d’écraser la branche latérale en un seul commit. mastercontinue d'avancer; comme il se doit - nous ne renversons pas de manière rétroactive des mois de développement parallèle dans l master'histoire de. Et si quelqu'un a besoin d'une meilleure résolution de l'histoire de la branche secondaire, eh bien, tout est toujours là: il n'est tout simplement pas masterinclus, c'est dans la branche latérale.

Voici le problème: je travaille exclusivement avec la ligne de commande, mais le reste de mon équipe utilise GUIS. Et j’ai découvert que les GUIS n’ont pas l’option raisonnable d’ afficher l’ historique des autres branches. Donc, si vous parvenez à un engagement au squash en disant "ce développement est écrasé XYZ", c'est très pénible d'aller voir ce qu'il y a dedans XYZ.

Pour SourceTree, dans la mesure où je suis capable de le trouver, c’est un mal de tête énorme: si vous êtes sur masteret que vous voulez voir l’historique master+devFeature, vous devez soit vérifier master+devFeature(en touchant chaque fichier qui est différent), soit faites défiler un journal affichant TOUTES les branches de votre référentiel en parallèle jusqu'à ce que vous trouviez le bon emplacement. Et bonne chance pour savoir où vous êtes.

Mes coéquipiers, à juste titre, ne veulent pas avoir une histoire de développement aussi inaccessible. Ils veulent donc que ces grandes et longues branches axées sur le développement soient fusionnées, toujours avec un engagement de fusion. Ils ne veulent pas d’historique qui ne soit pas immédiatement accessible depuis la branche principale.

Je déteste cette idée; cela signifie un enchevêtrement sans fin et non navigable dans l’histoire du développement parallèle. Mais je ne vois pas quelle alternative nous avons. Et je suis assez dérouté; cela semble bloquer presque tout ce que je sais sur la bonne gestion des succursales, et ma frustration sera constante si je ne trouve pas de solution.

Avons-nous une option ici en dehors de la fusion constante de branches secondaires en maître avec des commits de fusion? Ou bien, y a-t-il une raison pour laquelle l'utilisation constante de fusions par fusion n'est pas aussi mauvaise que je le crains?

Standback
la source
84
L'enregistrement d'une fusion en tant que fusion est-il vraiment si mauvais? Je peux voir que se glisser dans une histoire linéaire a ses avantages, mais je suis surpris que ne pas le faire va à l'encontre de "presque tout ce que vous savez sur la bonne gestion des succursales". Quels sont exactement les problèmes dont vous avez peur?
IMSoP
65
OK, mais dans mon esprit, une branche de longue date est exactement ce que vous voulez de visibilité, de sorte que les reproches et les ténèbres ne tombent pas sur "le changement a été introduit dans le cadre de la Grande Réécriture de 2016". Je ne suis pas assez en confiance pour répondre, mais mon instinct est que ce sont les tâches de la branche qui doivent être écrasées, de sorte que vous ayez une courte histoire du projet accessible à partir de l'historique principal, sans avoir à Découvrez une branche orpheline.
IMSoP
5
Cela étant dit, il est tout à fait possible que la question se réduise à la question suivante: "J'essaie d'utiliser un git à un niveau supérieur à celui de mes coéquipiers; comment puis-je les empêcher de tout gâcher pour moi?" Honnêtement, honnêtement, je ne m'attendais pas git log master+bugfixDec10thà être le point de rupture: - /
Standback
26
"Les branches secondaires à long terme - le genre où vous avez quelques personnes qui travaillent dans une branche qui se sépare de maître, nous développons pendant quelques mois, et lorsque nous atteignons un jalon, nous synchronisons les deux." Ne tirez-vous pas périodiquement du maître dans la branche latérale? Faire que chaque (quelques) engagements à maîtriser tend à rendre la vie plus simple dans de nombreux cas.
TafT
4
Est merge --no-ffce que tu veux? Sur masterlui-même, vous avez un commit qui décrit ce qui a changé dans la branche, mais tous les commits existent toujours et sont apparentés à HEAD.
CAD97

Réponses:

243

Même si j'utilise Git sur la ligne de commande, je suis d'accord avec vos collègues. Il n'est pas judicieux d'écraser de gros changements dans un seul commit. Vous perdez ainsi l’histoire et ne la rendez pas moins visible.

Le contrôle du code source consiste à suivre l'historique de toutes les modifications. Quand a changé quoi pourquoi? À cette fin, chaque commit contient des pointeurs sur les commits parents, un diff et des métadonnées comme un message de commit. Chaque commit décrit l'état du code source et l'historique complet de toutes les modifications ayant conduit à cet état. Le ramasse-miettes peut supprimer des validations inaccessibles.

Des actions telles que le rebasement, le tri sélectif ou l'écrasement suppriment ou réécrivent l'historique. En particulier, les commits résultants ne font plus référence aux commits d'origine. Considère ceci:

  • Vous écrasez certaines validations et notez dans le message de validation que l'historique écrasé est disponible dans la validation initiale abcd123.
  • Vous supprimez [1] toutes les branches ou étiquettes qui incluent abcd123 depuis leur fusion.
  • Vous laissez le ramasse-miettes s'exécuter.

[1]: Certains serveurs Git permettent de protéger les branches contre toute suppression accidentelle, mais je doute que vous souhaitiez conserver toutes vos branches de fonctionnalités pour l'éternité.

Maintenant, vous ne pouvez plus rechercher ce commit, il n'existe tout simplement pas.

Référencer un nom de branche dans un message de validation est encore pire, car les noms de branche sont locaux dans un référentiel. Ce qui est master+devFeaturedans votre caisse locale pourrait être doodlediduhdans la mienne. Les branches ne font que déplacer des étiquettes qui pointent sur un objet de validation.

Parmi toutes les techniques de réécriture d’historique, le rebasement est le plus inoffensif, car il duplique les validations complètes avec tout leur historique et ne fait que remplacer une validation parent.

Que l' masterhistoire comprenne l'histoire complète de toutes les branches qui ont été fusionnées est une bonne chose, car cela représente la réalité. [2] S'il y avait un développement parallèle, cela devrait être visible dans le journal.

[2]: Pour cette raison, je préfère également les commits de fusion explicites sur l’historique linéarisé, mais finalement faux, résultant d’un changement de base.

Sur la ligne de commande, git logessayez de simplifier l'historique affiché et de garder tous les commits affichés pertinents. Vous pouvez modifier la simplification de l'historique en fonction de vos besoins. Vous pourriez être tenté d'écrire votre propre outil de journal git qui parcourt le graphique de validation, mais il est généralement impossible de répondre «ce commit a-t-il été commis à l'origine sur telle ou telle branche?». Le premier parent d'une validation de fusion est la précédente HEAD, c'est-à-dire la validation de la branche dans laquelle vous fusionnez. Mais cela suppose que vous n'avez pas effectué de fusion inverse de maître dans la branche de fonctionnalité, puis de transfert rapide du maître vers la fusion.

La meilleure solution que j'ai rencontrée pour les branches à long terme consiste à empêcher les branches fusionnées de fusionner après quelques mois. La fusion est plus facile lorsque les modifications sont récentes et minimes. Idéalement, vous fusionnerez au moins une fois par semaine. L’intégration continue (comme dans Extreme Programming, et non pas dans «configurons un serveur Jenkins»), suggère même plusieurs fusions par jour, c’est-à-dire non pour conserver des branches distinctes, mais pour partager une branche de développement en équipe. Pour effectuer une fusion avant une fonctionnalité, QA exige que celle-ci soit masquée derrière un indicateur de fonctionnalité.

En contrepartie, une intégration fréquente permet de détecter les problèmes potentiels beaucoup plus tôt et contribue à maintenir une architecture cohérente: des changements de grande portée sont possibles, car ces changements sont rapidement inclus dans toutes les branches. Si un changement casse un code, il ne durera que quelques jours de travail, pas quelques mois.

La réécriture de l'historique peut avoir un sens pour des projets vraiment énormes lorsqu'il existe plusieurs millions de lignes de code et des centaines ou des milliers de développeurs actifs. On peut se demander pourquoi un projet d'une telle envergure devrait être un référentiel Git unique au lieu d'être divisé en bibliothèques séparées, mais à cette échelle, il est plus pratique que le référentiel central ne contienne que des «versions» des composants individuels. Par exemple, le noyau Linux utilise l'écrasement pour garder l'historique principal gérable. Certains projets open source nécessitent l’envoi de correctifs par courrier électronique, au lieu d’une fusion au niveau git.

Amon
la source
43
@Standback Je me fiche de ce qu'un développeur fait localement… utilisez des commits «wip», des commits supplémentaires pour chaque typo corrigée,…. C'est bien, il vaut mieux s'engager trop souvent. Idéalement, le développeur nettoie ces commits avant qu'ils ne soient poussés, comme si vous combiniez tous les commits ne corrigeant que quelques fautes de frappe. C'est toujours une bonne idée de séparer les commits s'ils font différentes choses, par exemple un commit pour les fonctionnalités réelles et les tests associés, un autre pour les fautes de frappe non liées. Mais une fois que les commits sont validés, la réécriture ou la suppression de l’historique est une gêne qu’il ne vaut pas la peine, du moins selon mon expérience.
amon
11
"il est généralement impossible de répondre:" ce commit a-t-il été commis à l'origine sur telle ou telle branche? "" Je vois le fait que les "branches" ne sont que des indicateurs de commits, sans historique particulier, l'un des plus gros défauts de conception de git Je veux vraiment pouvoir demander à mon système de contrôle de version «ce qui était dans la branche x à la date y".
Peter Green
80
Rien n’est plus frustrant que d’essayer d’identifier la cause d’un bogue dans le code git bisect, mais seulement de le faire arriver à un uber-commit de 10 000 lignes à partir d’une branche latérale.
tpg2114
2
@Standback IMHO plus le commit est petit, plus il est lisible et convivial. Un commit qui touche plus de quelques points est impossible à saisir au premier abord, vous devez donc prendre la description à la lettre. Il s’agit de la lisibilité de la description (par exemple, "fonctionnalité implémentée X"), pas du commit (code) lui-même. Je préférerais avoir 1 000 commits d'une lettre du type "modifié http en https"
:)
2
cherry-pick ne réécrit ni ne supprime l'historique. cela crée juste de nouveaux commits qui répliquent les modifications des commits existants
Sarge Borsch
110

J'aime la réponse d’Amon , mais j’ai pensé qu’une petite partie méritait plus d’attention: vous pouvez facilement simplifier l’historique tout en consultant des journaux pour répondre à vos besoins, mais d’autres ne peuvent pas ajouter d’historique tout en consultant des journaux pour répondre à leurs besoins. C'est pourquoi il est préférable de conserver l'historique tel qu'il s'est passé.

Voici un exemple tiré de l'un de nos référentiels. Nous utilisons un modèle à demande tirée, de sorte que chaque fonctionnalité ressemble à vos branches longues de l'histoire, même si elles n'exécutent généralement qu'une semaine ou moins. Les développeurs individuels choisissent parfois d'écraser leur historique avant de fusionner, mais nous nous associons souvent à des fonctionnalités, ce qui est relativement inhabituel. Voici le top des derniers commits gitk, l'interface graphique fournie avec git:

vue standard gitk

Oui, un peu enchevêtrement, mais nous aimons aussi parce que nous pouvons voir précisément qui a changé quoi à quelle heure. Cela reflète fidèlement notre histoire de développement. Si nous voulons voir une vue de niveau supérieur, fusion d'une demande d'extraction à la fois, nous pouvons examiner la vue suivante, qui équivaut à la git log --first-parentcommande:

vue gitk avec --first-parent

git loga beaucoup plus d'options conçues pour vous donner précisément les vues que vous voulez. gitkpeut prendre n'importe quel git logargument arbitraire pour construire une vue graphique. Je suis sûr que d'autres interfaces graphiques ont des capacités similaires. Lisez la documentation et apprenez à l'utiliser correctement, plutôt que d'appliquer votre git logvision préférée à tout le monde au moment de la fusion.

Karl Bielefeldt
la source
24
Je ne connaissais pas cette option! C’est une aide précieuse pour moi, et il semblerait que l’apprentissage d’autres options de journalisation me permettra de vivre avec cela plus facilement.
Standback
25
+1 pour "Vous pouvez facilement simplifier l'historique lors de la visualisation des journaux pour répondre à vos besoins, mais les autres utilisateurs ne peuvent pas ajouter d'historique lors de la visualisation des journaux pour répondre à leurs besoins." Réécrire l'histoire est toujours discutable. Si vous pensiez qu'il était important d'enregistrer au moment de commettre, c'était important. Même si vous avez trouvé que c'était faux ou si vous l'avez refait plus tard, cela fait partie de l'histoire. Certaines erreurs n’ont de sens que lorsque vous pouvez voir dans le blâme que cette dernière ligne a été laissée lors d’une réécriture ultérieure. Lorsque des erreurs sont incorporées au reste de l’épopée, vous ne pouvez pas savoir pourquoi les choses se sont terminées comme elles sont.
TafT
@Standback Related, une chose qui m'aide à conserver cette structure est d'utiliser merge --no-ff- n'utilisez pas de fusions à avance rapide, mais créez toujours un commit de fusion afin de --first-parentpouvoir travailler avec quelque chose
Izkata
34

Notre problème concerne les branches secondaires à long terme - du genre où vous avez quelques personnes qui travaillent dans une branche qui se sépare de master, nous développons pendant quelques mois et lorsque nous atteignons un jalon, nous synchronisons les deux.

Ma première pensée est la suivante: ne faites même pas cela à moins que cela ne soit absolument nécessaire. Vos fusions doivent parfois être difficiles. Gardez les branches indépendantes et aussi courtes que possible. C'est un signe que vous devez diviser vos histoires en plus petits morceaux de mise en œuvre.

Si vous devez le faire, il est possible de fusionner dans l'option git avec l'option --no-ff afin que les historiques restent distincts sur leur propre branche. Les commits apparaîtront toujours dans l'historique fusionné, mais pourront également être vus séparément dans la branche de la fonctionnalité afin qu'il soit au moins possible de déterminer la ligne de développement à laquelle ils appartenaient.

Je dois admettre que lorsque j'ai commencé à utiliser git, j'ai trouvé un peu étrange que les commits de branche apparaissent dans la même histoire que la branche principale après la fusion. C'était un peu déconcertant car il ne semblait pas que ces commits appartenaient à cette histoire. Mais dans la pratique, ce n’est pas vraiment pénible, si l’on considère que la branche d’intégration n’est que cela, c’est tout son objectif est de combiner les différentes branches. Dans notre équipe, nous n'écrasons pas et nous effectuons des commits de fusion fréquents. Nous utilisons --no-ff à tout moment pour s’assurer qu’il est facile de consulter l’historique exact de toute fonctionnalité si nous souhaitons l’examiner.

Brad Thomas
la source
3
Je suis tout à fait d'accord tout le monde préfère rester près du maître. Mais c'est une question différente, qui est beaucoup plus grande et beaucoup moins sous ma propre humble influence :-P
Standback
2
+1 pourgit merge --no-ff
0xcaff
1
Aussi +1 pour git merge --no-ff. Si vous utilisez gitflow, cela devient la valeur par défaut.
David Hammen
10

Permettez-moi de répondre à vos points directement et clairement:

Notre problème concerne les branches secondaires à long terme - du genre où vous avez quelques personnes qui travaillent dans une branche qui se sépare de master, nous développons pendant quelques mois et lorsque nous atteignons un jalon, nous synchronisons les deux.

Vous ne voulez généralement pas laisser vos branches non synchronisées pendant des mois.

Votre branche de fonctionnalité a dérivé de quelque chose en fonction de votre flux de travail; appelons-le simplement masterpour des raisons de simplicité. Maintenant, chaque fois que vous vous engagez à maîtriser, vous pouvez et devriez git checkout long_running_feature ; git rebase master. Cela signifie que vos branches sont, de par leur conception, toujours synchronisées.

git rebaseC'est aussi la bonne chose à faire ici. Ce n'est pas un hack ou quelque chose d'étrange ou de dangereux, mais complètement naturel. Vous perdez une information, qui correspond à "l'anniversaire" de la branche de fonctionnalité, mais c'est tout. Si quelqu'un trouve cela important, vous pouvez le faire en le conservant ailleurs (dans votre système de billetterie ou, si le besoin se fait sentir, dans un git tag...).

Maintenant, à mon humble avis, la façon naturelle de gérer cela est d’écraser la branche latérale en un seul commit.

Non, vous ne voulez absolument pas cela, vous voulez un commit de fusion. Une validation de fusion est également une "validation unique". En quelque sorte, il n’insère pas tous les commits de branche individuels "dans" le maître. Il s’agit d’un simple commit avec deux parents - le masterchef et le chef de succursale au moment de la fusion.

Assurez-vous de spécifier l' --no-ffoption, bien sûr; la fusion sans --no-ffdevrait, dans votre scénario, être strictement interdite. Malheureusement, ce --no-ffn'est pas la valeur par défaut; mais je crois qu’il existe une option que vous pouvez définir pour le rendre tel. Voir git help mergepour quoi --no-fffait (en bref: il active le comportement que j'ai décrit dans le paragraphe précédent), il est crucial.

Nous ne sommes pas en train de jeter rétroactivement des mois de développement parallèle dans l'histoire de Master.

Absolument pas - vous ne dormez jamais quelque chose "dans l'historique" d'une branche, surtout pas avec un commit de fusion.

Et si quelqu'un a besoin d'une meilleure résolution de l'histoire de la branche secondaire, eh bien, tout est toujours là - ce n'est tout simplement pas dans le fichier maître, c'est dans la branche latérale.

Avec un commit de fusion, il est toujours là. Pas en maître, mais dans la branche latérale, clairement visible en tant que l’un des parents du groupe fusionné et conservé pour l’éternité, comme il se doit.

Tu vois ce que j'ai fait? Toutes les choses que vous décrivez pour votre commit squash sont exactement là avec le --no-ffcommit de fusion .

Voici le problème: je travaille exclusivement avec la ligne de commande, mais le reste de mon équipe utilise GUIS.

(Remarque: je travaille presque exclusivement avec la ligne de commande également (eh bien, c’est un mensonge, j’utilise habituellement emacs magit, mais c’est une autre histoire - si je ne suis pas dans un endroit pratique avec ma configuration individuelle emacs, je préfère la commande mais faites-vous plaisir et essayez au moins git guiune fois. C’est tellement plus efficace pour choisir des lignes, des mecs, etc. pour ajouter / annuler des ajouts.)

Et j’ai découvert que les GUIS n’ont pas une option raisonnable pour afficher l’historique des autres branches.

C'est parce que ce que vous essayez de faire est totalement contraire à l'esprit de git. gitconstruit à partir du noyau d’un "graphe acyclique dirigé", ce qui signifie que beaucoup d’informations se trouvent dans la relation parent-enfant des commits. Et, pour les fusions, cela signifie de véritables commits de fusion avec deux parents et un enfant. Les interfaces graphiques de vos collègues iront très bien dès que vous utiliserez des no-ffcommits de fusion.

Donc, si vous atteignez un engagement au squash en disant "ce développement est écrasé de la branche XYZ", il est très pénible d'aller voir ce qu'il y a dans XYZ.

Oui, mais ce n’est pas un problème de l’interface graphique, mais du commit squash. L'utilisation d'un squash signifie que vous laissez la tête de la branche fonctionnelle pendante et que vous créez un nouveau commit dans master. Cela casse la structure à deux niveaux, créant un gros désordre.

Ils veulent donc que ces grandes et longues branches axées sur le développement soient fusionnées, toujours avec un engagement de fusion.

Et ils ont absolument raison. Mais ils ne sont pas « fusionnés dans », ils sont tout simplement fusionnés. Une fusion est une chose vraiment équilibrée, elle n’a aucun côté préféré qui soit fusionné "dans" l’autre ( git checkout A ; git merge Bexactement la même chose que git checkout B ; git merge Apour les différences visuelles mineures telles que les branches échangées, git logetc.).

Ils ne veulent pas d’historique qui ne soit pas immédiatement accessible depuis la branche principale.

Ce qui est complètement correct. À une époque où il n’existait aucune fonctionnalité non fusionnée, une seule branche masteravec une histoire riche encapsulait toutes les lignes de validation des fonctionnalités qui existaient, remontant à la git initvalidation depuis le début des temps (notez que j’ai évité précisément d’utiliser le terme " branches "dans la dernière partie de ce paragraphe car l'historique à ce moment-là n'est plus" des branches ", bien que le graphe de commit soit assez ramifié).

Je déteste cette idée;

Ensuite, vous souffrez un peu, car vous travaillez contre l’outil que vous utilisez. L' gitapproche est très élégante et puissante, en particulier dans le domaine des branches / fusions; si vous le faites correctement (comme mentionné ci-dessus, en particulier avec --no-ff), c'est par sauts et limites supérieur à d'autres approches (par exemple, le désordre de subversion d'avoir des structures de répertoires parallèles pour les branches).

cela signifie un enchevêtrement sans fin et non navigable dans l’histoire du développement parallèle.

Sans fin, parallèle - oui.

Inavigable, enchevêtrement - non.

Mais je ne vois pas quelle alternative nous avons.

Pourquoi ne pas travailler comme l'inventeur de git, vos collègues et le reste du monde, tous les jours?

Avons-nous une option ici en dehors de la fusion constante de branches secondaires en maître avec des commits de fusion? Ou bien, y a-t-il une raison pour laquelle l'utilisation constante de fusions par fusion n'est pas aussi mauvaise que je le crains?

Pas d'autres options pas aussi mauvais.

AnoE
la source
10

Réduire une branche latérale à long terme vous ferait perdre beaucoup d’informations.

Ce que je ferais, c’est d’ essayer de rebaser maître dans la branche secondaire à long terme avant de fusionner celle-ci en maître . De cette façon, vous gardez chaque commit en maître, tout en rendant l’historique des commit linéaire et plus facile à comprendre.

Si je ne pouvais pas le faire facilement à chaque engagement, je le laisserais non linéaire , afin de garder le contexte de développement clair. À mon avis, si j’ai un problème de fusion lors de la reconstitution de master en sidebranche, cela signifie que la non-linéarité a une signification réelle. Cela signifie qu’il sera plus facile de comprendre ce qui s’est passé au cas où j’aurais besoin de fouiller dans l’histoire. J'ai aussi l'avantage immédiat de ne pas avoir à refaire.

Pierre.Sassoulas
la source
: + pour mentionner rebase. Que ce soit ou non la meilleure approche ici (personnellement, je n’ai pas eu de grandes expériences avec cela, bien que je ne l’aie pas beaucoup utilisé), cela semble définitivement être ce qui se rapproche le plus de ce que OP semble vraiment vouloir - un compromis entre une décharge d’historique désordonnée et la dissimulation complète de cette histoire.
Kyle Strand
1

Personnellement, je préfère faire mon développement dans une fourchette, puis extraire les demandes pour les fusionner dans le référentiel principal.

Cela signifie que si je veux baser mes modifications sur le maître ou écraser certaines commissions WIP, je peux tout à fait le faire. Ou je peux simplement demander que toute mon histoire soit également fusionnée.

Ce que j'aime faire, c'est faire mon développement sur une branche mais me rebase souvent contre master / dev. De cette façon, je reçois les modifications les plus récentes du maître sans avoir beaucoup de commits de fusion dans ma branche, ni de gérer de nombreux conflits de fusion lorsqu'il est temps de fusionner.

Pour répondre explicitement à votre question:

Avons-nous une option ici en dehors de la fusion constante de branches secondaires en maître avec des commits de fusion?

Oui, vous pouvez les fusionner une fois par branche (lorsque la fonctionnalité ou le correctif est "terminé") ou si vous n'aimez pas que la fusion soit validée dans votre historique, vous pouvez simplement effectuer une fusion rapide en avant sur le maître après une refonte finale.

Wayne Werner
la source
3
Je suis désolé - je fais la même chose, mais je ne vois pas comment cela répond à la question: - /
Standback
2
Ajout d'une réponse explicite à votre question.
Wayne Werner
Donc, ça va pour mes propres engagements, mais moi (et mon équipe) nous occuperons du travail de tout le monde . Garder ma propre histoire propre est facile; Travailler dans une histoire de développement désordonnée est le problème ici.
Standback
Vous voulez dire que vous voulez avoir besoin d'autres développeurs pour ... quoi? Pas rebase et juste écraser sur la fusion? Ou posiez-vous simplement cette question pour vous plaindre du manque de discipline des git chez vos collègues?
Wayne Werner
1
il est inutile de modifier régulièrement les bases si plusieurs développeurs travaillent sur cette branche.
Paŭlo Ebermann
-1

Le contrôle de révision est garbage-in.

Le problème est que le travail en cours sur la branche de fonctionnalité peut contenir beaucoup de "essayons ceci ... non cela n'a pas fonctionné, remplaçons-le par cela" et tous les commits sauf le "final" final en polluant inutilement l’histoire.

En fin de compte, l'historique doit être conservé (une partie peut être utile dans le futur), mais seule une "copie vierge" doit être fusionnée.

Avec Git, cela peut être fait en commençant par brancher la branche de fonctionnalités (pour conserver tout l'historique), puis en rebasonnant (de manière interactive) la branche de la branche de caractéristiques depuis le maître, puis en fusionnant la branche rebasée.

DepressedDaniel
la source
1
Juste pour clarifier: ce que vous dites, c’est de réécrire l’historique sur (une copie) de la branche de fonctionnalité. Il a donc un historique court et clair, éliminant tous les va-et-vient du développement initial. Et puis, la fusion de la branche réécrite en maître est plus simple et plus propre. Vous ai-je bien compris?
Standback
1
Oui. Et lorsque vous fusionnez en maître, ce sera juste une avance rapide (en supposant que vous ayez rebasé récemment avant de fusionner).
DepressedDaniel
Mais comment cette histoire est-elle alors conservée? Laissez-vous la branche de fonctionnalité originale traîner?
Paŭlo Ebermann
@ Bingo PaŭloEbermann.
DepressedDaniel
Eh bien, comme quelqu'un l'a dit dans un commentaire: les branches ne sont que des pointeurs dans le graphique d'historique git, elles sont locales. Ce qui est nommé foodans un dépôt peut être nommé bardans un autre. Et elles sont censées être temporaires: vous ne voulez pas encombrer votre repo avec des milliers de branches de fonctionnalités qui doivent être maintenues en vie afin d'éviter de perdre l'historique. Et vous auriez besoin de conserver ces branches pour que l’historique reste la référence, car gitil supprimera éventuellement tout commit qui n’est plus accessible par une branche.
cmaster