Gestion des branches dans git


Git et les plateformes basées sur Git sont devenues omniprésentes pour le gestion de versions du code. En même temps, puisque git est un outil avec de nombreuses fonctionnalités, il n'y a pas une seule façon officielle de l'utiliser. Rechercher "git branching model" (modèle de branchement de git) produit des articles contenant des informations parfois contradictoires, qui peuvent être déroutant, en particulier pour les nouveaux utilisateurs.

Cet article a pour but de résumer les pratiques standard de développent avec git qui sont utilisées dans les logiciels open-source, et en particulier dans la communauté de Python scientifique. Ce workflow est une variation du "Github flow" popularisé par Github. Il vise à être simple et facile à comprendre, avec une approche recommandé, tout en permettant d'être ajusté au besoin pour les situations et les scénarios de déploiement plus complexes.

Idées principales

L'idée générale du worflow git proposé est illustrée sur la figure suivante.

La branche principale de développement, "master" doit toujours contenir du code fonctionnel et prêt à être déployé. Pour effectuer des modifications de code, on crée une nouvelle branche pour chaque fonctionnalité ou correction. Puis, on fait une Pull Request (PR), c'est à dire une demande pour inclure le code dans la branche master. Par exemple,

git checkout master
git checkout -b feature-1
# Make code changes
git commit -a -m "Adding feature 1"
git push

Une fois que la Pull Request a passé les contrôles de qualité, y compris les contrôles automatiques et la revue manuelle du code elle peut être fusionné dans master. Il est recommandé d'utiliser l'intégration Continue pour exécuter automatiquement les tests unitaires pour chaque commit.

Pour effectuer produire une nouvelle version ou un déploiements, on crée une étiquette (tag) sur la branche master, par exemple

git checkout master
git tag v0.1.0
git push origin v0.1.0

Notes:

  • Lors de la fusion des PR, il est préférable d'écraser l'historique (bouton "Merge & Squash" sur Github). Cela permet d'obtenir un seul commit sur master par Pull Request, ce qui permet de garder l'histoire propre et de transférer les modifications apportées aux d'autres branches.
  • Vous devez donner des noms explicites aux branches. Par exemple, pour une correction de défaut qui corrige une erreur d'overflow dans les matrices éparses, le nom de la branche pourrait être "fix-overflow-sparse".
  • Pour synchroniser ou résoudre les conflits dans une branche, on peut y fusionnez la branche master: git fetch origin && git merge origin/master N'utilisez pas rebaseet ne réécrivez pas l'histoire des PR, car cela rendrait plus difficile l'examen de changements consécutifs pendant la revue de code.
  • N'oubliez pas de toujours revenir à master (git checkout master) avant de créer de nouvelles branches.

Travailler avec des forks, et contribuer à des projets open-source

Il arrive fréquemment que l'on ait besoin de contribuer à un projet sans avoir l'accès en écriture à son dépôt. C'est notamment le cas pour la plupart des les projets à source ouverte.

Dans ce cas, Github, Gitlab et d'autres plateformes d'hébergement de git ont un mécanisme de fork. Il s'agit de faire une copie du dépôt à un endroit que l'on peut modifier (origin), et à partir duquel on peut faire des Pull Requests vers le dépôt principal (upstream).

Le déroulement des opérations dans ce cas, illustré sur la figure suivante, est très similaire à celui de la section précédente. On crée toujours des branches pour les nouvelles fonctionnalités, sauf que les PR sont faites à la branche master du dépôt upstream.

Pour synchroniser la branche master de votre fork avec les modifications du dépôt upstream, on ferait,

git remote add upstream <upstream-repo-url>  # just once
git fetch upstream
git checkout master
git rebase upstream/master

Les Pull Requests peuvent être synchronisées avec une démarche similaire, mais en utilisant,

git merge upstream/master

à la place du rebase.

Notes:

  • ne faites jamais des PRs de la branche master du votre fork, créez toujours un branche spécifique pour chaque modification.
  • Une fois qu'une Pull Request est fusionnée, sa branche peut être supprimée.

Ajout des branches de maintenance

Pour les projets plus importants, il peut être utile de faire des nouvelles version qui ajoutent des corrections de défaut sans les nouvelles fonctionnalités.

Dans ce cas, nous pouvons créer une branche de maintenance à partir de l'étiquette (tag) de la dernière version. Les nouvelles fonctionnalités et les corrections de défauts sont d'abord ajoutées dans master. Les corrections de défaut sont alors copiés, en utilisant par exemple git cherry-pick <commit-hash> vers le branche de maintenance.

Une nouvelle étiquette (tag) peut ensuite ajoutée sur la branche de maintance pour faire une nouvelle version.

Conclusions

Nous avons examiné un flux de développent simple qui peut être utilisé pour de nouveaux projets ou pour commencer à contribuer aux projets open-source. Pour une discussion plus détaillée sur la gestion de branches dans git, voir par exemple l'initial sur GitLab flow.