GitHub Flow

Problèmes avec git-flow

Je voyage partout pour enseigner Git aux gens et presque chaque classe et atelier que j’ai fait récemment m’a demandé ce que je pense de git-flow. Je réponds toujours que je pense que c’est génial – il a pris un système (Git) qui a un million de flux de travail possibles et a documenté un flux de travail bien testé et flexible qui fonctionne pour beaucoup de développeurs d’une manière assez simple. Il est devenu une sorte de norme, de sorte que les développeurs peuvent se déplacer entre les projets ou les entreprises et être familiers avec ce flux de travail normalisé.

Cependant, il a ses problèmes. J’ai entendu un certain nombre d’opinions de personnes du genre à ne pas aimer que les branches de nouvelles fonctionnalités soient démarrées à partir de develop plutôt que de master, ou la façon dont il gère les hotfixes, mais ce sont des problèmes assez mineurs.

Un des plus gros problèmes pour moi est qu’il est plus compliqué que ce dont je pense que la plupart des développeurs et des équipes de développement ont réellement besoin. C’est assez compliqué pour qu’un grand script d’aide ait été développé pour aider à faire respecter le flux. Bien que ce soit cool, le problème est qu’il ne peut pas être appliqué dans une interface graphique Git, seulement en ligne de commande, donc les seules personnes qui doivent apprendre le flux complexe vraiment bien, parce qu’ils doivent faire toutes les étapes manuellement, sont les mêmes personnes qui ne sont pas assez à l’aise avec le système pour l’utiliser à partir de la ligne de commande. Cela peut être un énorme problème.

Ces deux problèmes peuvent être résolus facilement simplement en ayant un processus beaucoup plus simplifié. Chez GitHub, nous n’utilisons pas git-flow. Nous utilisons, et avons toujours utilisé, un flux de travail Git beaucoup plus simple.

Sa simplicité lui confère un certain nombre d’avantages. L’un d’eux est qu’il est facile à comprendre pour les gens, ce qui signifie qu’ils peuvent le prendre rapidement et qu’ils ne le gâchent que rarement, voire jamais, ou qu’ils doivent défaire les étapes qu’ils ont mal faites. Un autre est que nous n’avons pas besoin d’un script enveloppant pour aider à l’appliquer ou à le suivre, donc l’utilisation d’interfaces graphiques et autres ne sont pas un problème.

GitHub Flow

Alors, pourquoi n’utilisons-nous pas git-flow chez GitHub ? Eh bien, le principal problème est que nous déployons tout le temps. Le processus git-flow est conçu en grande partie autour de la « release ». Nous n’avons pas vraiment de « releases » car nous déployons en production tous les jours – souvent plusieurs fois par jour. Nous pouvons le faire par le biais de notre robot de salon de discussion, qui est le même endroit où sont affichés les résultats de nos CI. Nous essayons de rendre le processus de test et d’expédition aussi simple que possible afin que chaque employé se sente à l’aise pour le faire.

Il y a un certain nombre d’avantages à déployer aussi régulièrement. Si vous déployez toutes les quelques heures, il est presque impossible d’introduire un grand nombre de gros bugs. De petits problèmes peuvent être introduits, mais alors ils peuvent être corrigés et redéployés très rapidement. Normalement, vous devriez faire un « hotfix » ou quelque chose en dehors du processus normal, mais cela fait simplement partie de notre processus normal – il n’y a pas de différence dans le flux GitHub entre un hotfix et une très petite fonctionnalité.

Un autre avantage du déploiement tout le temps est la capacité de traiter rapidement les problèmes de toutes sortes. Nous pouvons répondre aux problèmes de sécurité qui sont portés à notre attention ou mettre en œuvre des demandes de fonctionnalités petites mais intéressantes incroyablement rapidement, et pourtant, nous pouvons utiliser exactement le même processus pour traiter ces changements que pour gérer le développement de fonctionnalités normales ou même importantes. C’est le même processus et c’est très simple.

Comment nous le faisons

Alors, qu’est-ce que GitHub Flow ?

  • Tout ce qui se trouve dans la branche master est déployable
  • Pour travailler sur quelque chose de nouveau, créez une branche au nom descriptif à partir de master (ie : new-oauth2-scopes)
  • Commit à cette branche localement et poussez régulièrement votre travail vers la même branche nommée sur le serveur
  • Quand vous avez besoin de commentaires ou d’aide, ou que vous pensez que la branche est prête à être fusionnée, ouvrez une demande de pull
  • Après que quelqu’un d’autre ait revu et signé la fonctionnalité, vous pouvez la fusionner dans master
  • Une fois qu’elle est fusionnée et poussée vers ‘master’, vous pouvez et devez déployer immédiatement

C’est le flux entier. Il est très simple, très efficace et fonctionne pour des équipes assez importantes – GitHub compte 35 employés maintenant, dont peut-être 15-20 travaillent sur le même projet (github.com) en même temps. Je pense que la plupart des équipes de développement – des groupes qui travaillent sur le même code logique en même temps, ce qui pourrait produire des conflits – sont de cette taille ou plus petites. Surtout ceux qui sont assez progressifs pour faire des déploiements rapides et cohérents.

Donc, examinons chacune de ces étapes à tour de rôle.

#1 – tout ce qui est dans la branche maîtresse est déployable

C’est fondamentalement la seule règle dure du système. Il n’y a qu’une seule branche qui a une signification spécifique et cohérente et nous l’avons nommée master. Pour nous, cela signifie qu’elle a été déployée ou, au pire, qu’elle le sera dans les heures qui suivent. Il est incroyablement rare que cela soit rewound (la branche est déplacée vers un commit plus ancien pour revenir sur le travail) – s’il y a un problème, les commits seront reverted ou de nouveaux commits seront introduits qui corrigent le problème, mais la branche elle-même n’est presque jamais rolled back.

La branche master est stable et il est toujours, toujours sûr de déployer à partir d’elle ou de créer de nouvelles branches à partir d’elle. Si vous poussez quelque chose vers master qui n’est pas testé ou qui casse la construction, vous brisez le contrat social de l’équipe de développement et vous vous sentez normalement assez mal à ce sujet. Chaque branche que nous poussons a des tests exécutés sur elle et rapportés dans le salon de discussion, donc si vous ne les avez pas exécutés localement, vous pouvez simplement pousser vers une branche topic (même une branche avec un seul commit) sur le serveur et attendre que Jenkins vous dise si elle passe tout.

Vous pourriez avoir une branche deployed qui est mise à jour uniquement lorsque vous déployez, mais nous ne le faisons pas. Nous exposons simplement le SHA actuellement déployé à travers la webapp elle-même et curlil si nous avons besoin d’une comparaison faite.

#2 – créer des branches descriptives à partir de master

Lorsque vous voulez commencer à travailler sur quoi que ce soit, vous créez une branche au nom descriptif à partir de la branche stable master. Quelques exemples dans la base de code GitHub en ce moment seraient user-content-cache-key, submodules-init-task ou redis2-transition. Cela a plusieurs avantages – l’un est que lorsque vous récupérez, vous pouvez voir les sujets sur lesquels tout le monde a travaillé. Un autre est que si vous abandonnez une branche pendant un certain temps et que vous y revenez plus tard, il est assez facile de se rappeler ce que c’était.

C’est bien parce que lorsque nous allons sur la page de la liste des branches de GitHub, nous pouvons facilement voir quelles branches ont été travaillées récemment et à peu près combien de travail elles ont sur elles.

github branch list

C’est presque comme une liste de fonctionnalités à venir avec le statut approximatif actuel. Cette page est géniale si vous ne l’utilisez pas – elle ne vous montre que les branches qui ont un travail unique sur elles par rapport à votre branche actuellement sélectionnée et elle les trie de sorte que les plus récemment travaillées soient en haut. Si je suis vraiment curieux, je peux cliquer sur le bouton ‘Compare’ pour voir ce que sont le diff et la liste de commit unifiés réels qui sont uniques à cette branche.

Donc, au moment où j’écris ces lignes, nous avons 44 branches dans notre dépôt avec du travail non fusionné dans celles-ci, mais je peux aussi voir que seulement environ 9 ou 10 d’entre elles ont été poussées vers au cours de la dernière semaine.

#3 – pousser vers des branches nommées constamment

Une autre grande différence avec git-flow est que nous poussons vers des branches nommées sur le serveur constamment. Puisque la seule chose dont nous devons vraiment nous préoccuper est master du point de vue du déploiement, pousser vers le serveur ne perturbe personne et ne rend pas les choses confuses – tout ce qui n’est pas master est simplement quelque chose sur lequel on travaille.

Cela permet également de s’assurer que notre travail est toujours sauvegardé en cas de perte d’ordinateur portable ou de panne de disque dur. Plus important encore, il met tout le monde en communication constante. Un simple ‘git fetch’ vous donnera essentiellement une liste TODO de ce sur quoi tout le monde travaille actuellement.

$ git fetchremote: Counting objects: 3032, done.remote: Compressing objects: 100% (947/947), done.remote: Total 2672 (delta 1993), reused 2328 (delta 1689)Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.Resolving deltas: 100% (1993/1993), completed with 213 local objects.From github.com:github/github * charlock-linguist -> origin/charlock-linguist * enterprise-non-config -> origin/enterprise-non-config * fi-signup -> origin/fi-signup 2647a42..4d6d2c2 git-http-server -> origin/git-http-server * knyle-style-commits -> origin/knyle-style-commits 157d2b0..d33e00d master -> origin/master * menu-behavior-act-i -> origin/menu-behavior-act-i ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config * svg-tests -> origin/svg-tests 87bb870..9da23f3 view-modes -> origin/view-modes * wild-renaming -> origin/wild-renaming

Il permet également à tout le monde de voir, en regardant la page GitHub Branch List, sur quoi tout le monde travaille afin qu’ils puissent les inspecter et voir s’ils veulent aider avec quelque chose.

#4 – ouvrir une demande de pull à tout moment

GitHub a un système de révision de code incroyable appelé Pull Requests que je crains que pas assez de gens connaissent. Beaucoup de gens l’utilisent pour le travail open source – fork un projet, mettre à jour le projet, envoyer une demande de pull au mainteneur. Cependant, il peut aussi facilement être utilisé comme un système de revue de code interne, ce que nous faisons.

En fait, nous l’utilisons plus comme une vue de conversation de branche plus que comme une demande de pull. Vous pouvez envoyer des pull requests d’une branche à l’autre dans un seul projet (public ou privé) dans GitHub, donc vous pouvez les utiliser pour dire « J’ai besoin d’aide ou de révision sur ceci » en plus de « S’il vous plaît, fusionnez ceci dedans ».

early pr message

Ici vous pouvez voir Josh cc’ing Brian pour la révision et Brian venant avec quelques conseils sur l’une des lignes de code. Plus bas, nous pouvons voir Josh reconnaître les préoccupations de Brian et pousser plus de code pour y répondre.

plus de discussion

Enfin, vous pouvez voir que nous sommes toujours dans la phase d’essai – ce n’est pas encore une branche prête à être déployée, nous utilisons les Pull Requests pour revoir le code bien avant de vouloir effectivement le fusionner dans master pour le déploiement.

Si vous êtes bloqué dans la progression de votre fonctionnalité ou de votre branche et que vous avez besoin d’aide ou de conseils, ou si vous êtes un développeur et que vous avez besoin qu’un designer révise votre travail (ou vice versa), ou même si vous avez peu ou pas de code mais quelques comps de captures d’écran ou des idées générales, vous ouvrez une pull request. Vous pouvez cc les gens dans le système GitHub en ajoutant un @username, donc si vous voulez l’examen ou la rétroaction de personnes spécifiques, il suffit de les cc dans le message PR (comme vous avez vu Josh faire ci-dessus).

C’est cool parce que la fonctionnalité Pull Request vous permet de commenter des lignes individuelles dans le diff unifié, sur des commits uniques ou sur la pull request elle-même et tire tout en ligne à une vue de conversation unique.Il vous permet également de continuer à pousser vers la branche, donc si quelqu’un commente que vous avez oublié de faire quelque chose ou qu’il y a un bug dans le code, vous pouvez le corriger et pousser vers la branche, GitHub montrera les nouveaux commits dans la vue de conversation et vous pouvez continuer à itérer sur une branche comme ça.

Si la branche est ouverte depuis trop longtemps et que vous sentez qu’elle se désynchronise avec la branche maître, vous pouvez fusionner maître dans votre branche sujet et continuer. Vous pouvez facilement voir dans la discussion de la pull request ou dans la liste des commit quand la branche a été mise à jour pour la dernière fois avec le ‘master’.

master merge

Quand tout est vraiment et réellement fait sur la branche et que vous sentez qu’elle est prête à être déployée, vous pouvez passer à l’étape suivante.

#5 – fusionner seulement après revue de pull request

Nous ne faisons pas simplement le travail directement sur master ou le travail sur une branche de sujet et le fusionner dans quand nous pensons que c’est fait – nous essayons d’obtenir la signature de quelqu’un d’autre dans l’entreprise. Il s’agit généralement d’un +1 ou d’un emoji ou d’un commentaire « :shipit:« , mais nous essayons de faire en sorte que quelqu’un d’autre y jette un œil.

shipit comment

Une fois que nous l’avons obtenu, et que la branche passe le CI, nous pouvons la fusionner dans master pour le déploiement, ce qui fermera automatiquement la Pull Request lorsque nous la pousserons.

#6 – déployer immédiatement après la révision

Finalement, votre travail est terminé et fusionné dans la branche master. Cela signifie que même si vous ne le déployez pas maintenant, les gens vont baser un nouveau travail dessus et le prochain déploiement, qui aura probablement lieu dans quelques heures, le poussera. Donc, puisque vous ne voulez vraiment pas que quelqu’un d’autre pousse quelque chose que vous avez écrit et qui casse des choses, les gens ont tendance à s’assurer que c’est vraiment stable quand il est fusionné et les gens ont également tendance à pousser leurs propres changements.

Notre bot de feu de camp, hubot, peut faire des déploiements pour n’importe quel employé, donc un simple:

hubot depoy github to production

déploiera le code et le zéro-downtime redémarrera tous les processus nécessaires. Vous pouvez voir à quel point cela est courant sur GitHub:

nos journaux de feu de camp

Vous pouvez voir 6 personnes différentes (y compris un gars du support et un concepteur) déployer environ 24 fois en un jour.

J’ai fait cela pour des branches avec un commit contenant un changement d’une ligne. Le processus est simple, direct, évolutif et puissant. Vous pouvez le faire avec des branches de fonctionnalités avec 50 commits sur eux qui ont pris 2 semaines, ou 1 commit qui a pris 10 minutes. C’est un processus tellement simple et sans friction que vous n’êtes pas ennuyé de devoir le faire même pour 1 commit, ce qui signifie que les gens essaient rarement de sauter ou de contourner le processus, à moins que le changement soit si petit ou insignifiant que cela n’a tout simplement pas d’importance.

C’est un processus incroyablement simple et puissant. Je pense que la plupart des gens seraient d’accord pour dire que GitHub dispose d’une plateforme très stable, que les problèmes sont traités rapidement, si jamais ils se présentent, et que de nouvelles fonctionnalités sont introduites à un rythme rapide. Il n’y a pas de compromis de qualité ou de stabilité pour que nous puissions obtenir plus de vitesse ou de simplicité ou moins de processus.

Conclusion

Git lui-même est assez complexe à comprendre, rendre le flux de travail que vous utilisez avec lui plus complexe que nécessaire est simplement ajouter plus de surcharge mentale à la journée de tout le monde. Je préconiserais toujours d’utiliser le système le plus simple possible qui fonctionnera pour votre équipe et de le faire jusqu’à ce qu’il ne fonctionne plus, puis d’ajouter de la complexité uniquement si cela est absolument nécessaire.

Pour les équipes qui doivent faire des versions formelles à plus long terme (quelques semaines à quelques mois entre les versions), et être en mesure de faire des corrections à chaud et des branches de maintenance et d’autres choses qui découlent de l’expédition si peu fréquente, git-flow a du sens et je préconiserais fortement son utilisation.

Pour les équipes qui ont mis en place une culture d’expédition, qui poussent vers la production tous les jours, qui testent et déploient constamment, je préconiserais de choisir quelque chose de plus simple comme GitHub Flow.

Leave a Reply