Slide 1

Slide 1 text

Git ʙ Stratégies Session 2 / 4 Matti Schneider @matti_sg Les éléments soulignés dans les notes signifient qu'il faut passer à l'étape suivante de l'animation interne à la slide (soit la page suivante dans le PDF).

Slide 2

Slide 2 text

Prérequis 2 Pour suivre efficacement cette session, vous devriez : - Savoir ce que sont les branches dans un système de gestion de versions, de préférence Git (un rappel sera néanmoins fait). - Savoir que Git est un système décentralisé. - Connaître les objectifs de la qualité logicielle (maintenabilité, déployabilité…). Les deux premiers points sont enseignés dans la première session de formation.

Slide 3

Slide 3 text

Prérequis • gestion des branches 2 Pour suivre efficacement cette session, vous devriez : - Savoir ce que sont les branches dans un système de gestion de versions, de préférence Git (un rappel sera néanmoins fait). - Savoir que Git est un système décentralisé. - Connaître les objectifs de la qualité logicielle (maintenabilité, déployabilité…). Les deux premiers points sont enseignés dans la première session de formation.

Slide 4

Slide 4 text

Prérequis • gestion des branches • décentralisation 2 Pour suivre efficacement cette session, vous devriez : - Savoir ce que sont les branches dans un système de gestion de versions, de préférence Git (un rappel sera néanmoins fait). - Savoir que Git est un système décentralisé. - Connaître les objectifs de la qualité logicielle (maintenabilité, déployabilité…). Les deux premiers points sont enseignés dans la première session de formation.

Slide 5

Slide 5 text

Prérequis • gestion des branches • décentralisation • qualité logicielle 2 Pour suivre efficacement cette session, vous devriez : - Savoir ce que sont les branches dans un système de gestion de versions, de préférence Git (un rappel sera néanmoins fait). - Savoir que Git est un système décentralisé. - Connaître les objectifs de la qualité logicielle (maintenabilité, déployabilité…). Les deux premiers points sont enseignés dans la première session de formation.

Slide 6

Slide 6 text

Stratégies… ? 3 Cette session définira des “stratégies”. À proprement parler, il s'agit de conventions et méthodes permettant de travailler dans un environnement de haute qualité logicielle, où le déploiement est fiable, la collaboration est efficace (minimisation des conflits et verrous d'édition), et où la base de code est plus facilement maintenable (minimisation des régressions, en particulier aux intégrations ; traçabilité du code).

Slide 7

Slide 7 text

Stratégies… ? • Conventions & Méthodes 3 Cette session définira des “stratégies”. À proprement parler, il s'agit de conventions et méthodes permettant de travailler dans un environnement de haute qualité logicielle, où le déploiement est fiable, la collaboration est efficace (minimisation des conflits et verrous d'édition), et où la base de code est plus facilement maintenable (minimisation des régressions, en particulier aux intégrations ; traçabilité du code).

Slide 8

Slide 8 text

Stratégies… ? • Conventions & Méthodes • sécurité du déploiement 3 Cette session définira des “stratégies”. À proprement parler, il s'agit de conventions et méthodes permettant de travailler dans un environnement de haute qualité logicielle, où le déploiement est fiable, la collaboration est efficace (minimisation des conflits et verrous d'édition), et où la base de code est plus facilement maintenable (minimisation des régressions, en particulier aux intégrations ; traçabilité du code).

Slide 9

Slide 9 text

Stratégies… ? • Conventions & Méthodes • sécurité du déploiement • collaboration efficace 3 Cette session définira des “stratégies”. À proprement parler, il s'agit de conventions et méthodes permettant de travailler dans un environnement de haute qualité logicielle, où le déploiement est fiable, la collaboration est efficace (minimisation des conflits et verrous d'édition), et où la base de code est plus facilement maintenable (minimisation des régressions, en particulier aux intégrations ; traçabilité du code).

Slide 10

Slide 10 text

Stratégies… ? • Conventions & Méthodes • sécurité du déploiement • collaboration efficace • maintenabilité 3 Cette session définira des “stratégies”. À proprement parler, il s'agit de conventions et méthodes permettant de travailler dans un environnement de haute qualité logicielle, où le déploiement est fiable, la collaboration est efficace (minimisation des conflits et verrous d'édition), et où la base de code est plus facilement maintenable (minimisation des régressions, en particulier aux intégrations ; traçabilité du code).

Slide 11

Slide 11 text

Objectifs 4 À la fin de cette session, vous devriez connaître : - Des conventions de gestion de branches efficaces. - Les contrats passés avec les clients de vos APIs lorsque vous étiquetez votre code par des numéros de version. - La manipulation des sous-modules dans Git, un moyen de compartimenter efficacement votre code.

Slide 12

Slide 12 text

Objectifs 1. Stratégie de branchement. 4 À la fin de cette session, vous devriez connaître : - Des conventions de gestion de branches efficaces. - Les contrats passés avec les clients de vos APIs lorsque vous étiquetez votre code par des numéros de version. - La manipulation des sous-modules dans Git, un moyen de compartimenter efficacement votre code.

Slide 13

Slide 13 text

Objectifs 1. Stratégie de branchement. 2. Versionnement sémantique. 4 À la fin de cette session, vous devriez connaître : - Des conventions de gestion de branches efficaces. - Les contrats passés avec les clients de vos APIs lorsque vous étiquetez votre code par des numéros de version. - La manipulation des sous-modules dans Git, un moyen de compartimenter efficacement votre code.

Slide 14

Slide 14 text

Objectifs 1. Stratégie de branchement. 2. Versionnement sémantique. 3. Sous-modules. 4 À la fin de cette session, vous devriez connaître : - Des conventions de gestion de branches efficaces. - Les contrats passés avec les clients de vos APIs lorsque vous étiquetez votre code par des numéros de version. - La manipulation des sous-modules dans Git, un moyen de compartimenter efficacement votre code.

Slide 15

Slide 15 text

Branches

Slide 16

Slide 16 text

Branches – Rappels 6 Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 17

Slide 17 text

Branches – Rappels 6 Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 18

Slide 18 text

Branches – Rappels 6 master $ git branch * master Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 19

Slide 19 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese cheese Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 20

Slide 20 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese cheese Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 21

Slide 21 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… cheese Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 22

Slide 22 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master cheese Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 23

Slide 23 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master $ git checkout -b eggs cheese eggs Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 24

Slide 24 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master $ git checkout -b eggs # commit, commit… cheese eggs Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 25

Slide 25 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master $ git checkout -b eggs # commit, commit… $ git checkout master cheese eggs Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 26

Slide 26 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master $ git checkout -b eggs # commit, commit… $ git checkout master $ git merge eggs cheese eggs Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 27

Slide 27 text

Branches – Rappels 6 master $ git branch * master $ git branch cheese $ git checkout cheese # commit, commit… $ git checkout master $ git checkout -b eggs # commit, commit… $ git checkout master $ git merge eggs branche branche intégration (merge) cheese eggs Une branche est essentiellement un pointeur vers un commit spécifique. Pour lister l'ensemble des branches existantes, on utilise branch sans argument. Git fournit toujours par défaut la branche master. Pour créer une nouvelle branche, on utilise la commande branch. Nous avons ajouté ici la branche cheese. Pour changer de branche, on utilise la commande checkout. Si l'on modifie un fichier sur la branche courante, puis que l'on commit ces modifications, le pointeur de la branche courante est mis à jour vers le nouveau commit, et pas les autres branches. C'est donc là qu'une divergence apparaît. On a en parallèle deux versions différentes du même fichier, au même chemin. Si l'on retourne sur la branche master, les différences sont visibles directement dans le fichier modifié. Pour créer une nouvelle branche et basculer immédiatement dessus, on peut utiliser l'option -b de la commande checkout. Les commits suivants seront donc faits sur la nouvelle branche. Pour intégrer les modifications dans une autre branche, on commence par basculer sur la destination, puis on utilise la commande merge, pour effectuer une intégration.

Slide 28

Slide 28 text

Suppression de branches 7 master cheese eggs À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 29

Slide 29 text

Suppression de branches 7 master $ git branch eggs * master cheese cheese eggs À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 30

Slide 30 text

Suppression de branches 7 master $ git branch eggs * master cheese $ git branch -d eggs cheese eggs À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 31

Slide 31 text

Suppression de branches 7 master $ git branch eggs * master cheese $ git branch -d eggs Deleted branch eggs (was 23e94d) cheese À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 32

Slide 32 text

Suppression de branches 7 master $ git branch eggs * master cheese $ git branch -d eggs Deleted branch eggs (was 23e94d) $ git branch -d cheese cheese À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 33

Slide 33 text

Suppression de branches 7 master $ git branch eggs * master cheese $ git branch -d eggs Deleted branch eggs (was 23e94d) $ git branch -d cheese error: The branch 'cheese' is not fully merged. cheese À partir de ces outils de base, nous allons ajouter des conventions permettant de répondre aux objectifs de sécurité et d'efficacité de gestion du code source. Reprenons donc nos branches précédentes. Pour en supprimer une, on utilise l'option -d (delete) de la commande branch. La suppression de cette branche consiste simplement en la suppression d'un pointeur vers un commit, absolument pas en la suppression des commits en eux-mêmes. Essayons à présent de supprimer l'autre branche. Git refuse de détruire une branche dont tous les commits n'ont pas été intégrés. Cela est permis par l'identification de chaque commit de manière unique par son contenu. Il s'agit donc d'un filet de sécurité nous permettant de supprimer systématiquement les branches après intégration, afin de minimiser le nombre de branches visibles, sans se soucier de perdre des informations : dans le cas d'une erreur, Git refusera d'effectuer une commande destructrice.

Slide 34

Slide 34 text

GitHub Flow 8 master Nous allons à présent étudier une stratégie de nommage et de gestion des branches formalisée par GitHub : le GitHub Flow. La première convention est que la branche master est toujours déployable. À partir du dernier commit, par définition fiable, de la branche master, on crée des “feature branches”, c'est-à-dire des branches ayant pour objectif d'aboutir à la réalisation d'une fonctionnalité spécifique. On nomme chacune de ces branches le plus explicitement possible, d'après la fonctionnalité à implémenter. Une fois la fonctionnalité réalisée, testée et validée en isolation, on intègre la “feature branch” correspondante dans master, et on la supprime : ce sont des branches temporaires, dont l'objectif est d'isoler les développements. En cas d'échec (fonctionnalité abandonnée, mauvaise implémentation…), chacune de ces branches étant implicitement expérimentale, il suffit de la supprimer sans impacter la branche principale, depuis laquelle les déploiements sont effectués.

Slide 35

Slide 35 text

GitHub Flow 8 master Toujours déployable Nous allons à présent étudier une stratégie de nommage et de gestion des branches formalisée par GitHub : le GitHub Flow. La première convention est que la branche master est toujours déployable. À partir du dernier commit, par définition fiable, de la branche master, on crée des “feature branches”, c'est-à-dire des branches ayant pour objectif d'aboutir à la réalisation d'une fonctionnalité spécifique. On nomme chacune de ces branches le plus explicitement possible, d'après la fonctionnalité à implémenter. Une fois la fonctionnalité réalisée, testée et validée en isolation, on intègre la “feature branch” correspondante dans master, et on la supprime : ce sont des branches temporaires, dont l'objectif est d'isoler les développements. En cas d'échec (fonctionnalité abandonnée, mauvaise implémentation…), chacune de ces branches étant implicitement expérimentale, il suffit de la supprimer sans impacter la branche principale, depuis laquelle les déploiements sont effectués.

Slide 36

Slide 36 text

GitHub Flow 8 master Toujours déployable cheese nutella “Feature branches” Nous allons à présent étudier une stratégie de nommage et de gestion des branches formalisée par GitHub : le GitHub Flow. La première convention est que la branche master est toujours déployable. À partir du dernier commit, par définition fiable, de la branche master, on crée des “feature branches”, c'est-à-dire des branches ayant pour objectif d'aboutir à la réalisation d'une fonctionnalité spécifique. On nomme chacune de ces branches le plus explicitement possible, d'après la fonctionnalité à implémenter. Une fois la fonctionnalité réalisée, testée et validée en isolation, on intègre la “feature branch” correspondante dans master, et on la supprime : ce sont des branches temporaires, dont l'objectif est d'isoler les développements. En cas d'échec (fonctionnalité abandonnée, mauvaise implémentation…), chacune de ces branches étant implicitement expérimentale, il suffit de la supprimer sans impacter la branche principale, depuis laquelle les déploiements sont effectués.

Slide 37

Slide 37 text

GitHub Flow 8 master Toujours déployable cheese nutella “Feature branches” Nous allons à présent étudier une stratégie de nommage et de gestion des branches formalisée par GitHub : le GitHub Flow. La première convention est que la branche master est toujours déployable. À partir du dernier commit, par définition fiable, de la branche master, on crée des “feature branches”, c'est-à-dire des branches ayant pour objectif d'aboutir à la réalisation d'une fonctionnalité spécifique. On nomme chacune de ces branches le plus explicitement possible, d'après la fonctionnalité à implémenter. Une fois la fonctionnalité réalisée, testée et validée en isolation, on intègre la “feature branch” correspondante dans master, et on la supprime : ce sont des branches temporaires, dont l'objectif est d'isoler les développements. En cas d'échec (fonctionnalité abandonnée, mauvaise implémentation…), chacune de ces branches étant implicitement expérimentale, il suffit de la supprimer sans impacter la branche principale, depuis laquelle les déploiements sont effectués.

Slide 38

Slide 38 text

GitHub Flow 8 master Toujours déployable cheese nutella “Feature branches” Expérimental Nous allons à présent étudier une stratégie de nommage et de gestion des branches formalisée par GitHub : le GitHub Flow. La première convention est que la branche master est toujours déployable. À partir du dernier commit, par définition fiable, de la branche master, on crée des “feature branches”, c'est-à-dire des branches ayant pour objectif d'aboutir à la réalisation d'une fonctionnalité spécifique. On nomme chacune de ces branches le plus explicitement possible, d'après la fonctionnalité à implémenter. Une fois la fonctionnalité réalisée, testée et validée en isolation, on intègre la “feature branch” correspondante dans master, et on la supprime : ce sont des branches temporaires, dont l'objectif est d'isoler les développements. En cas d'échec (fonctionnalité abandonnée, mauvaise implémentation…), chacune de ces branches étant implicitement expérimentale, il suffit de la supprimer sans impacter la branche principale, depuis laquelle les déploiements sont effectués.

Slide 39

Slide 39 text

Git-flow 9 master Toujours déployable cheese nutella “Feature branches” Expérimental En gardant à l'esprit ces concepts de “feature branches” et de garantie de déployabilité de master, nous allons voir une autre stratégie de gestion des branches, plus complexe : git-flow.

Slide 40

Slide 40 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 41

Slide 41 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 42

Slide 42 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 43

Slide 43 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 44

Slide 44 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 45

Slide 45 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration hotfix release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 46

Slide 46 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration hotfix release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 47

Slide 47 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration hotfix release nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 48

Slide 48 text

Git-flow 10 master Toujours déployable cheese “Feature branches” Expérimental develop Intégration hotfix release Temporaires nutella En plus de master, on ajoute une branche permanente d'intégration, généralement nommée “develop”. C'est depuis et vers elle que les “feature branches” seront branchées. En revanche, cette branche n'a pas vocation à être déployable directement. Si l'on veut déployer de nouvelles fonctionnalités, on le fait en passant par une branche temporaire de release, généralement nommée d'après la version de destination. Une fois les préparations pour le déploiement faites, d'éventuels tests manuels passés, on intègre la branche de release dans master. Les modifications sont également, pour ne pas être perdues, appliquées à la branche d'intégration. En cas de problème repéré sur la version en production, on branche directement master sur une branche temporaire “hotfix”, nommée d'après le bug à corriger. Une fois la correction finalisée, on l'intègre bien évidemment dans master pour appliquer les corrections… mais également dans la branche d'intégration, pour éviter toute régression dans une prochaine release. Il faut bien comprendre que les deux seules branches permanentes sont master et la branche d'intégration. Toutes les autres sont supprimées dès leur intégration terminée (ou leur abandon).

Slide 49

Slide 49 text

Collaboration sur branches 11 origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 50

Slide 50 text

Collaboration sur branches 11 $ git checkout -b cheese origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 51

Slide 51 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 52

Slide 52 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 53

Slide 53 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 54

Slide 54 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 55

Slide 55 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master $ git checkout -b ham origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 56

Slide 56 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master $ git checkout -b ham # commit, commit… origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 57

Slide 57 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master $ git checkout -b ham # commit, commit… $ git push origin ham origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 58

Slide 58 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master $ git checkout -b ham # commit, commit… $ git push origin ham ! [rejected] ham -> ham error: failed to push some refs… origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 59

Slide 59 text

Collaboration sur branches 11 $ git checkout -b cheese $ git pull origin cheese # commit, commit… $ git push origin cheese $ git checkout master $ git checkout -b ham # commit, commit… $ git push origin ham ! [rejected] ham -> ham error: failed to push some refs… $ git pull origin ham origin local Ces conventions nécessitant de nombreuses manipulations de branches, nous allons voir comment collaborer sur branches dans un environnement distribué. Prenons le cas de la récupération d'une branche distante existante, déjà populée par un collaborateur. Pour la récupérer en local, le plus simple est de suivre la procédure suivante : - créer une branche locale du même nom que la branche distante ; - récupérer la branche distante par un pull. On peut ainsi facilement travailler en local sur une feature branch. Pour propager ses modifications, on utilise push, mais en spécifiant sur quelle “remote” (machine distante) et sur quelle branche distante. Revenons à présent sur notre branche master, pour créer une nouvelle feature branch, sur laquelle on applique des modifications. Il suffit ensuite d'envoyer ses modifications sur le serveur par push. Néanmoins, il peut arriver que Git refuse la propagation. Une telle situation apparaît quand un collaborateur a lui aussi effectué des modifications sur son dépôt local. Pour corriger le problème, il faut donc d'abord récupérer les modifications distantes, corriger les

Slide 60

Slide 60 text

Stratégies de branchement 12 Nous avons vu deux stratégies de branchement : git-flow et GitHub Flow. Tant que le déploiement peut être fait facilement, nous vous conseillons d'utiliser le plus simple, à savoir le GitHub Flow. Dans un contexte où déployer une nouvelle version est plus coûteux (embarqué, application desktop…), le git-flow et son système de validation plus lourd peut s'avérer plus indiqué. Autant que possible, allez vers le plus simple possible pour éviter de perdre du temps à gérer le code au lieu d'en écrire. Dans tous les cas, ces stratégies sont des classiques, mais rien ne vous empêche de créer les vôtres ! La seule règle qui paraît réellement systématique est l'utilisation d'une branche permanente dont la déployabilité est garantie. Ainsi, revenir à une version précédente en cas de problème, ou profiter d'une opportunité de mise à jour, est simple et sans risque.

Slide 61

Slide 61 text

Stratégies de branchement 12 • GitHub flow si déploiement facile, git-flow sinon Nous avons vu deux stratégies de branchement : git-flow et GitHub Flow. Tant que le déploiement peut être fait facilement, nous vous conseillons d'utiliser le plus simple, à savoir le GitHub Flow. Dans un contexte où déployer une nouvelle version est plus coûteux (embarqué, application desktop…), le git-flow et son système de validation plus lourd peut s'avérer plus indiqué. Autant que possible, allez vers le plus simple possible pour éviter de perdre du temps à gérer le code au lieu d'en écrire. Dans tous les cas, ces stratégies sont des classiques, mais rien ne vous empêche de créer les vôtres ! La seule règle qui paraît réellement systématique est l'utilisation d'une branche permanente dont la déployabilité est garantie. Ainsi, revenir à une version précédente en cas de problème, ou profiter d'une opportunité de mise à jour, est simple et sans risque.

Slide 62

Slide 62 text

Stratégies de branchement 12 • GitHub flow si déploiement facile, git-flow sinon • keep it simple Nous avons vu deux stratégies de branchement : git-flow et GitHub Flow. Tant que le déploiement peut être fait facilement, nous vous conseillons d'utiliser le plus simple, à savoir le GitHub Flow. Dans un contexte où déployer une nouvelle version est plus coûteux (embarqué, application desktop…), le git-flow et son système de validation plus lourd peut s'avérer plus indiqué. Autant que possible, allez vers le plus simple possible pour éviter de perdre du temps à gérer le code au lieu d'en écrire. Dans tous les cas, ces stratégies sont des classiques, mais rien ne vous empêche de créer les vôtres ! La seule règle qui paraît réellement systématique est l'utilisation d'une branche permanente dont la déployabilité est garantie. Ainsi, revenir à une version précédente en cas de problème, ou profiter d'une opportunité de mise à jour, est simple et sans risque.

Slide 63

Slide 63 text

Stratégies de branchement 12 • GitHub flow si déploiement facile, git-flow sinon • keep it simple • une seule règle : master toujours déployable Nous avons vu deux stratégies de branchement : git-flow et GitHub Flow. Tant que le déploiement peut être fait facilement, nous vous conseillons d'utiliser le plus simple, à savoir le GitHub Flow. Dans un contexte où déployer une nouvelle version est plus coûteux (embarqué, application desktop…), le git-flow et son système de validation plus lourd peut s'avérer plus indiqué. Autant que possible, allez vers le plus simple possible pour éviter de perdre du temps à gérer le code au lieu d'en écrire. Dans tous les cas, ces stratégies sont des classiques, mais rien ne vous empêche de créer les vôtres ! La seule règle qui paraît réellement systématique est l'utilisation d'une branche permanente dont la déployabilité est garantie. Ainsi, revenir à une version précédente en cas de problème, ou profiter d'une opportunité de mise à jour, est simple et sans risque.

Slide 64

Slide 64 text

Versionnement

Slide 65

Slide 65 text

Tags 14 Pour enregistrer les versions, Git fournit un système d'étiquetage, les tags. Pour lister les tags, on utilise "tag" sans paramètre. Un tag ne doit pas contenir d'espace, mais on peut lui associer un message, comme un commit, via "-m". Un tag est une métadonnée pointant vers un commit spécifique. On peut donc en avoir vers autant de commits, dans autant de branches différentes, qu'on le souhaite. Pour ajouter un tag au dernier commit (HEAD), on utilise la commande tag avec le nom donné. On notera au passage que rien n'empêche de tagger plusieurs fois le même commit. En revanche, les tags doivent être uniques au sein du dépôt. Pour propager ses étiquettes, il faut le spécifier explicitement à Git, en utilisant push --tags. C'est seulement à cette condition que les étiquettes posées localement seront visibles sur un dépôt partagé. Ainsi, lorsque le système de versionnement est efficace, la commande de propagation devient souvent “git push && git push --tags”.

Slide 66

Slide 66 text

Tags $ git tag beta-2 v1.0 14 Pour enregistrer les versions, Git fournit un système d'étiquetage, les tags. Pour lister les tags, on utilise "tag" sans paramètre. Un tag ne doit pas contenir d'espace, mais on peut lui associer un message, comme un commit, via "-m". Un tag est une métadonnée pointant vers un commit spécifique. On peut donc en avoir vers autant de commits, dans autant de branches différentes, qu'on le souhaite. Pour ajouter un tag au dernier commit (HEAD), on utilise la commande tag avec le nom donné. On notera au passage que rien n'empêche de tagger plusieurs fois le même commit. En revanche, les tags doivent être uniques au sein du dépôt. Pour propager ses étiquettes, il faut le spécifier explicitement à Git, en utilisant push --tags. C'est seulement à cette condition que les étiquettes posées localement seront visibles sur un dépôt partagé. Ainsi, lorsque le système de versionnement est efficace, la commande de propagation devient souvent “git push && git push --tags”.

Slide 67

Slide 67 text

beta-2 Tags $ git tag beta-2 v1.0 14 v1.0 Pour enregistrer les versions, Git fournit un système d'étiquetage, les tags. Pour lister les tags, on utilise "tag" sans paramètre. Un tag ne doit pas contenir d'espace, mais on peut lui associer un message, comme un commit, via "-m". Un tag est une métadonnée pointant vers un commit spécifique. On peut donc en avoir vers autant de commits, dans autant de branches différentes, qu'on le souhaite. Pour ajouter un tag au dernier commit (HEAD), on utilise la commande tag avec le nom donné. On notera au passage que rien n'empêche de tagger plusieurs fois le même commit. En revanche, les tags doivent être uniques au sein du dépôt. Pour propager ses étiquettes, il faut le spécifier explicitement à Git, en utilisant push --tags. C'est seulement à cette condition que les étiquettes posées localement seront visibles sur un dépôt partagé. Ainsi, lorsque le système de versionnement est efficace, la commande de propagation devient souvent “git push && git push --tags”.

Slide 68

Slide 68 text

beta-2 Tags $ git tag beta-2 v1.0 $ git tag "v1.1" -m "Added cheese" $ git tag beta-2 v1.0 v1.1 14 v1.0 v1.1 Pour enregistrer les versions, Git fournit un système d'étiquetage, les tags. Pour lister les tags, on utilise "tag" sans paramètre. Un tag ne doit pas contenir d'espace, mais on peut lui associer un message, comme un commit, via "-m". Un tag est une métadonnée pointant vers un commit spécifique. On peut donc en avoir vers autant de commits, dans autant de branches différentes, qu'on le souhaite. Pour ajouter un tag au dernier commit (HEAD), on utilise la commande tag avec le nom donné. On notera au passage que rien n'empêche de tagger plusieurs fois le même commit. En revanche, les tags doivent être uniques au sein du dépôt. Pour propager ses étiquettes, il faut le spécifier explicitement à Git, en utilisant push --tags. C'est seulement à cette condition que les étiquettes posées localement seront visibles sur un dépôt partagé. Ainsi, lorsque le système de versionnement est efficace, la commande de propagation devient souvent “git push && git push --tags”.

Slide 69

Slide 69 text

beta-2 Tags $ git tag beta-2 v1.0 $ git tag "v1.1" -m "Added cheese" $ git tag beta-2 v1.0 v1.1 $ git push --tags 14 v1.0 v1.1 Pour enregistrer les versions, Git fournit un système d'étiquetage, les tags. Pour lister les tags, on utilise "tag" sans paramètre. Un tag ne doit pas contenir d'espace, mais on peut lui associer un message, comme un commit, via "-m". Un tag est une métadonnée pointant vers un commit spécifique. On peut donc en avoir vers autant de commits, dans autant de branches différentes, qu'on le souhaite. Pour ajouter un tag au dernier commit (HEAD), on utilise la commande tag avec le nom donné. On notera au passage que rien n'empêche de tagger plusieurs fois le même commit. En revanche, les tags doivent être uniques au sein du dépôt. Pour propager ses étiquettes, il faut le spécifier explicitement à Git, en utilisant push --tags. C'est seulement à cette condition que les étiquettes posées localement seront visibles sur un dépôt partagé. Ainsi, lorsque le système de versionnement est efficace, la commande de propagation devient souvent “git push && git push --tags”.

Slide 70

Slide 70 text

Semantic SemVer Versioning 15 Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 71

Slide 71 text

Semantic SemVer Versioning 15 v X . Y . Z Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 72

Slide 72 text

Semantic SemVer Versioning 15 v X . Y . Z bugfix Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 73

Slide 73 text

Semantic SemVer Versioning 15 v X . Y . Z bugfix feature Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 74

Slide 74 text

Semantic SemVer Versioning 15 v X . Y . Z bugfix feature new API Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 75

Slide 75 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 76

Slide 76 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 77

Slide 77 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Compatibilité API publique Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 78

Slide 78 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Compatibilité API publique ✔ Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 79

Slide 79 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Compatibilité API publique ✔ ✔* *dépréciation possible Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 80

Slide 80 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Compatibilité API publique ? ✔ ✔* *dépréciation possible Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 81

Slide 81 text

Semantic SemVer Versioning 15 v X . Y . Z Major Minor Patch bugfix feature new API – id Pre-rel “beta.1”, “alpha”… Compatibilité API publique ? ✔ ✔* *dépréciation possible ? Le versionnement sémantique, ou SemVer, est une simple convention de nommage. Vous utilisez certainement déjà un système proche : la lettre 'v', suivie de trois entiers positifs séparés par des points. L'incrémentation du dernier nombre à droite indique la correction d'une anomalie. Celle du nombre central, l'ajout d'une fonctionnalité. Enfin, celle du nombre le plus à gauche, une nouvelle version complète, généralement accompagnée une nouvelle API. On parlera de numéros de version “majeur”, “mineur” et “de patch”. On peut également ajouter à cette numérotation, en cas de besoin, un identifiant de pré-version, préfixé d'un tiret, et sans espace. Tout l'intérêt de ce système de versionnement est l'établissement d'un contrat avec les clients de l'API publique de votre application : - la modification d'un numéro de patch GARANTIT le maintien tel quel de votre API ; - la modification d'un numéro mineur GARANTIT la compatibilité de votre API, bien que certaines méthodes puissent être dépréciées en prévision d'évolutions ; - la modification d'un numéro majeur, quant à lui, n'offre aucune garantie : l'API a pu être modifiée, ou non. En revanche, toute incompatibilité d'API oblige à incrémenter le numéro de version majeur. Un identifiant de pré-version casse les contrats habituels. L'objectif est de respecter celui annoncé par le numéro de version, mais tant que la pré-version est présente, rien n'est certain.

Slide 82

Slide 82 text

SemVer & RDD 16 Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 83

Slide 83 text

SemVer & RDD • signaler la convention 16 SemVer .git ignore Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 84

Slide 84 text

SemVer & RDD • signaler la convention • définir l'objectif 16 SemVer v0.1.0 READ ME .git ignore Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 85

Slide 85 text

SemVer & RDD • signaler la convention • définir l'objectif • v0 : aucune API garantie 16 SemVer v0.1.0 READ ME .git ignore Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 86

Slide 86 text

SemVer & RDD • signaler la convention • définir l'objectif • v0 : aucune API garantie • v1 : toute modification est rétro-compatible 16 SemVer v0.1.0 READ ME .git ignore v1.0.0 Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 87

Slide 87 text

SemVer & RDD • signaler la convention • définir l'objectif • v0 : aucune API garantie • v1 : toute modification est rétro-compatible • pour l'API publique 16 SemVer v0.1.0 READ ME .git ignore v1.0.0 doc Voyons à présent comment appliquer ces concepts à l'étiquetage des commits, et la notion de ReadMe-Driven Development. Lors du premier commit sur votre dépôt, vous allez signaler le respect de la convention de versionnement sémantique, en étiquetant ce commit initial de “SemVer” (git tag "SemVer"). Dans ce premier commit, vous ajouterez quelques fichiers basiques (buildfile standard, architecture de fichiers générique…), mais aucun code ni documentation spécifique. Vos commits suivants seront dédiés à l'établissement d'une charte d'objectifs et de développement : le fameux fichier README, que vous placerez à la racine du dépôt, au format texte ou Markdown. Il est important de commencer par cette étape : c'est en formalisant les objectifs, en vous mettant à la place d'un autre développeur tentant de comprendre ce à quoi sert votre code que vous réfléchirez à l'architecture et éviterez les pièges d'un développement trop rapide. Une fois ce document finalisé, vous pourrez étiqueter la version 0.1.0 de votre projet, puis coder sans préoccupation tant que le numéro majeur reste 0, ce qui signifie une phase de développement rapide. En revanche, à partir de la version 1, toute modification doit respecter le contrat de ne pas casser l'API publique, ce qui implique de l'avoir correctement documentée dès la v1. En cas d'abandon de la compatibilité, aussi petite soit elle, une nouvelle version majeure doit être fournie, et la version ayant cassé la compatibilité ne doit plus être distribuée.

Slide 88

Slide 88 text

Stratégie de versionnement 17

Slide 89

Slide 89 text

Stratégie de versionnement 17 • versionnement obligatoire pour toute API publique

Slide 90

Slide 90 text

Stratégie de versionnement 17 • versionnement obligatoire pour toute API publique • changement incompatible ⇒ changement de version

Slide 91

Slide 91 text

Stratégie de versionnement 17 • versionnement obligatoire pour toute API publique • changement incompatible ⇒ changement de version • réfléchir avant de publier

Slide 92

Slide 92 text

Stratégie de versionnement 17 • versionnement obligatoire pour toute API publique • changement incompatible ⇒ changement de version • réfléchir avant de publier • v0 sans engagement

Slide 93

Slide 93 text

Stratégie de versionnement 17 • versionnement obligatoire pour toute API publique • changement incompatible ⇒ changement de version • réfléchir avant de publier • v0 sans engagement • développement rapide

Slide 94

Slide 94 text

Sous-modules

Slide 95

Slide 95 text

Sous-module 19 Un sous-module, conceptuellement, est un dépôt incorporé dans un autre dépôt, ce qui permet une approche composants. Une telle architecture permet d'augmenter la qualité du code résultant, par la compartimentation des différentes bibliothèques qu'elle propose. En conséquence, le code écrit est bien plus facilement partageable entre différents projets, ce qui augmente le retour sur investissement.

Slide 96

Slide 96 text

Sous-module • “un dépôt dans un dépôt” 19 Un sous-module, conceptuellement, est un dépôt incorporé dans un autre dépôt, ce qui permet une approche composants. Une telle architecture permet d'augmenter la qualité du code résultant, par la compartimentation des différentes bibliothèques qu'elle propose. En conséquence, le code écrit est bien plus facilement partageable entre différents projets, ce qui augmente le retour sur investissement.

Slide 97

Slide 97 text

Sous-module • “un dépôt dans un dépôt” • qualité • DRY (Don't Repeat Yourself) • cohésion • découplage • documentation 19 Un sous-module, conceptuellement, est un dépôt incorporé dans un autre dépôt, ce qui permet une approche composants. Une telle architecture permet d'augmenter la qualité du code résultant, par la compartimentation des différentes bibliothèques qu'elle propose. En conséquence, le code écrit est bien plus facilement partageable entre différents projets, ce qui augmente le retour sur investissement.

Slide 98

Slide 98 text

Sous-module • “un dépôt dans un dépôt” • qualité • DRY (Don't Repeat Yourself) • cohésion • découplage • documentation • réusabilité 19 Un sous-module, conceptuellement, est un dépôt incorporé dans un autre dépôt, ce qui permet une approche composants. Une telle architecture permet d'augmenter la qualité du code résultant, par la compartimentation des différentes bibliothèques qu'elle propose. En conséquence, le code écrit est bien plus facilement partageable entre différents projets, ce qui augmente le retour sur investissement.

Slide 99

Slide 99 text

Initialisation 20 .git Mon projet Pour gérer les sous-modules, on utilisera le jeu de commandes "git submodule". Pour ajouter un sous-module à un dépôt existant, on utilisera "submodule add", suivie de l'URL du dépôt à intégrer. Cela déclenchera tout d'abord l'ajout d'une entrée dans un fichier texte versionné, “.gitmodules”, à la racine du dépôt contenant, avant de cloner le dépôt cible comme "git clone" l'aurait fait directement. La liste des sous-modules (.gitmodules) étant versionnée, elle est partagée entre tous les collaborateurs du dépôt contenant. Néanmoins, cela n'est pas suffisant pour que Git puisse configurer le sous-module sur chaque copie du dépôt. Il faut donc, à chaque ajout d'un sous-module, utiliser la commande "submodule init". L'idée est de découpler la liste partagée des modules (amendée par "add") de la configuration spécifique à chaque machine ("init"). Pour lister l'ensemble des sous-modules du dépôt courant, on utilise "submodule" sans commande plus spécifique.

Slide 100

Slide 100 text

Initialisation $ git submodule add URL/dep.git Cloning into dep... done. 20 .git modules .git .git dep Mon projet Pour gérer les sous-modules, on utilisera le jeu de commandes "git submodule". Pour ajouter un sous-module à un dépôt existant, on utilisera "submodule add", suivie de l'URL du dépôt à intégrer. Cela déclenchera tout d'abord l'ajout d'une entrée dans un fichier texte versionné, “.gitmodules”, à la racine du dépôt contenant, avant de cloner le dépôt cible comme "git clone" l'aurait fait directement. La liste des sous-modules (.gitmodules) étant versionnée, elle est partagée entre tous les collaborateurs du dépôt contenant. Néanmoins, cela n'est pas suffisant pour que Git puisse configurer le sous-module sur chaque copie du dépôt. Il faut donc, à chaque ajout d'un sous-module, utiliser la commande "submodule init". L'idée est de découpler la liste partagée des modules (amendée par "add") de la configuration spécifique à chaque machine ("init"). Pour lister l'ensemble des sous-modules du dépôt courant, on utilise "submodule" sans commande plus spécifique.

Slide 101

Slide 101 text

Initialisation $ git submodule add URL/dep.git Cloning into dep... done. $ git submodule init Submodule 'dep' registered for path 'dep' 20 .git modules .git .git dep Mon projet [sub] url = dep … config Pour gérer les sous-modules, on utilisera le jeu de commandes "git submodule". Pour ajouter un sous-module à un dépôt existant, on utilisera "submodule add", suivie de l'URL du dépôt à intégrer. Cela déclenchera tout d'abord l'ajout d'une entrée dans un fichier texte versionné, “.gitmodules”, à la racine du dépôt contenant, avant de cloner le dépôt cible comme "git clone" l'aurait fait directement. La liste des sous-modules (.gitmodules) étant versionnée, elle est partagée entre tous les collaborateurs du dépôt contenant. Néanmoins, cela n'est pas suffisant pour que Git puisse configurer le sous-module sur chaque copie du dépôt. Il faut donc, à chaque ajout d'un sous-module, utiliser la commande "submodule init". L'idée est de découpler la liste partagée des modules (amendée par "add") de la configuration spécifique à chaque machine ("init"). Pour lister l'ensemble des sous-modules du dépôt courant, on utilise "submodule" sans commande plus spécifique.

Slide 102

Slide 102 text

Initialisation $ git submodule add URL/dep.git Cloning into dep... done. $ git submodule init Submodule 'dep' registered for path 'dep' $ git submodule +39b400e7f5cbb dep (heads/master) 20 .git modules .git .git dep Mon projet [sub] url = dep … config Pour gérer les sous-modules, on utilisera le jeu de commandes "git submodule". Pour ajouter un sous-module à un dépôt existant, on utilisera "submodule add", suivie de l'URL du dépôt à intégrer. Cela déclenchera tout d'abord l'ajout d'une entrée dans un fichier texte versionné, “.gitmodules”, à la racine du dépôt contenant, avant de cloner le dépôt cible comme "git clone" l'aurait fait directement. La liste des sous-modules (.gitmodules) étant versionnée, elle est partagée entre tous les collaborateurs du dépôt contenant. Néanmoins, cela n'est pas suffisant pour que Git puisse configurer le sous-module sur chaque copie du dépôt. Il faut donc, à chaque ajout d'un sous-module, utiliser la commande "submodule init". L'idée est de découpler la liste partagée des modules (amendée par "add") de la configuration spécifique à chaque machine ("init"). Pour lister l'ensemble des sous-modules du dépôt courant, on utilise "submodule" sans commande plus spécifique.

Slide 103

Slide 103 text

Modification 21 .git modules .git .git dep Mon projet On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 104

Slide 104 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) 21 .git modules .git .git dep Mon projet URL/dep @39b400 On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 105

Slide 105 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) 21 .git modules .git .git dep Mon projet URL/dep 39b400 @39b400 On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 106

Slide 106 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) $ cd dep # commit, push 21 .git modules .git .git dep Mon projet URL/dep @39b400 e92d8c On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 107

Slide 107 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) $ cd dep # commit, push $ cd .. ; git status # modified: dep (new commits) 21 .git modules .git .git dep Mon projet URL/dep @39b400 e92d8c On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 108

Slide 108 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) $ cd dep # commit, push $ cd .. ; git status # modified: dep (new commits) $ git add dep 21 .git modules .git .git dep Mon projet URL/dep @39b400 e92d8c On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 109

Slide 109 text

Modification $ git submodule +39b400e7f5cbb dep (heads/master) $ cd dep # commit, push $ cd .. ; git status # modified: dep (new commits) $ git add dep $ git commit -m "Updated" 21 .git modules .git .git dep Mon projet URL/dep e92d8c @e92d8c On a vu que lister les sous-modules donne un identifiant de commit et de branche en plus du chemin du dépôt intégré. Pour Git, un sous-module est en réalité représenté par l'URL de son dépôt, et l'identifiant du commit (état) dans lequel il est intégré dans le dépôt parent. Il faut bien comprendre cela : dans le système de fichiers, le dépôt complet est présent. Mais pour Git, seule une référence est présente : il s'agit d'un bloc à un certain commit, aucun fichier n'est suivi dans le dépôt parent. Cela a des conséquences pratiques. En particulier, si l'on effectue des modifications dans le sous-module. Son état courant, HEAD, est mis à jour par ces commits (ou par un checkout…). Le dépôt parent verra cette différence, mais pas sous la forme de modification des fichiers : il détectera de nouveaux commits dans le sous-module. Pour propager ce changement d'état du sous-module, on suit le processus standard : ajout des modifications dans l'aire d'assemblage, puis commit. C'est ce commit qui mettra à jour le pointeur vers sous-module dans le dépôt parent.

Slide 110

Slide 110 text

Mise à jour 22 Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 111

Slide 111 text

Mise à jour 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 112

Slide 112 text

Mise à jour $ cd sub; git pull; cd .. 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 113

Slide 113 text

Mise à jour $ cd sub; git pull; cd .. $ git submodule foreach git pull 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 114

Slide 114 text

Mise à jour $ cd sub; git pull; cd .. $ git submodule foreach git pull $ git submodule foreach --recursive git pull 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 115

Slide 115 text

Mise à jour $ cd sub; git pull; cd .. $ git submodule foreach git pull $ git submodule foreach --recursive git pull $ git commit -a -m "Updated submodules" 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 116

Slide 116 text

Mise à jour $ cd sub; git pull; cd .. $ git submodule foreach git pull $ git submodule foreach --recursive git pull $ git commit -a -m "Updated submodules" $ git push 22 superproject submodules nested submodules Nous avons vu comment appliquer de nouvelles modifications à un sous-module, mais pas encore comment récupérer des modifications appliquées par ailleurs sur son dépôt. Nous nous intéresserons en particulier au cas de sous-modules imbriqués. La manière la plus simple de mettre à jour un sous-module consiste à le considérer comme un dépôt standard, comme fait précédemment, et d'effectuer un simple pull. Néanmoins, cela devient rapidement ennuyeux lorsque de nombreux sous-modules sont intégrés. Git fournit pour cela la commande foreach, à laquelle vous pouvez passer n'importe quelle ligne de commande. Ici, nous utiliserons donc à nouveau git pull. Notez que nous aurions pu utiliser toute autre commande, y compris autre que git (sed…). "foreach" ne va cependant itérer que sur les sous-modules du dépôt courant. Si l'on souhaite suivre l'éventuel arbre d'imbrication des sous-modules, on utilise l'option --recursive. Dans tous les cas, une fois les mises à jour du contenu effectuées, il faut valider la mise à jour de la version du sous-module intégrée dans le dépôt parent. Cette étape ne devrait être accomplie qu'après s'être s'assuré que la nouvelle version du sous-module n'a rien cassé du dépôt parent. La propagation des modifications s'effectue toujours aussi simplement, par un push standard.

Slide 117

Slide 117 text

Collaboration 23 Plaçons-nous à présent dans le cas d'un clone du dépôt sur lequel nous venons de propager des modifications, qui n'a plus été mis à jour depuis longtemps. L'utilisation d'un pull mettra à jour la liste des sous-modules, et invalidera éventuellement les versions de certains sous-modules… mais ne les mettra pas à jour automatiquement ! Après la mise à jour du pointeur vers le commit souhaité du sous-module, pour mettre à jour le contenu du sous-module lui-même, il faut utiliser submodule update, qui effectuera un pull en cas de besoin, suivi d'une mise à jour du contenu au nouveau commit indiqué. Néanmoins, cela n'est pas suffisant en cas d'ajout d'un nouveau sous-module. Dans cette situation, un "submodule init" est nécessaire… ou l'utilisation de l'option "--init", qui appellera "submodule init" au besoin. Enfin, comme précédemment, pour que les sous-modules imbriqués soient eux aussi mis à jour et initialisés au besoin, on utilisera l'option "--recursive". En réalité, une fois les sous-modules faisant partie du mode de travail habituel, la commande de mise à jour du dépôt passe généralement de "git pull" à ¬ "git pull && git submodule update --init --recursive", cette dernière commande étant neutre en l'absence de modifications.

Slide 118

Slide 118 text

Collaboration $ git pull Fast-forward… "Updated submodules" 23 Plaçons-nous à présent dans le cas d'un clone du dépôt sur lequel nous venons de propager des modifications, qui n'a plus été mis à jour depuis longtemps. L'utilisation d'un pull mettra à jour la liste des sous-modules, et invalidera éventuellement les versions de certains sous-modules… mais ne les mettra pas à jour automatiquement ! Après la mise à jour du pointeur vers le commit souhaité du sous-module, pour mettre à jour le contenu du sous-module lui-même, il faut utiliser submodule update, qui effectuera un pull en cas de besoin, suivi d'une mise à jour du contenu au nouveau commit indiqué. Néanmoins, cela n'est pas suffisant en cas d'ajout d'un nouveau sous-module. Dans cette situation, un "submodule init" est nécessaire… ou l'utilisation de l'option "--init", qui appellera "submodule init" au besoin. Enfin, comme précédemment, pour que les sous-modules imbriqués soient eux aussi mis à jour et initialisés au besoin, on utilisera l'option "--recursive". En réalité, une fois les sous-modules faisant partie du mode de travail habituel, la commande de mise à jour du dépôt passe généralement de "git pull" à ¬ "git pull && git submodule update --init --recursive", cette dernière commande étant neutre en l'absence de modifications.

Slide 119

Slide 119 text

Collaboration $ git pull Fast-forward… "Updated submodules" $ git submodule update 23 Plaçons-nous à présent dans le cas d'un clone du dépôt sur lequel nous venons de propager des modifications, qui n'a plus été mis à jour depuis longtemps. L'utilisation d'un pull mettra à jour la liste des sous-modules, et invalidera éventuellement les versions de certains sous-modules… mais ne les mettra pas à jour automatiquement ! Après la mise à jour du pointeur vers le commit souhaité du sous-module, pour mettre à jour le contenu du sous-module lui-même, il faut utiliser submodule update, qui effectuera un pull en cas de besoin, suivi d'une mise à jour du contenu au nouveau commit indiqué. Néanmoins, cela n'est pas suffisant en cas d'ajout d'un nouveau sous-module. Dans cette situation, un "submodule init" est nécessaire… ou l'utilisation de l'option "--init", qui appellera "submodule init" au besoin. Enfin, comme précédemment, pour que les sous-modules imbriqués soient eux aussi mis à jour et initialisés au besoin, on utilisera l'option "--recursive". En réalité, une fois les sous-modules faisant partie du mode de travail habituel, la commande de mise à jour du dépôt passe généralement de "git pull" à ¬ "git pull && git submodule update --init --recursive", cette dernière commande étant neutre en l'absence de modifications.

Slide 120

Slide 120 text

Collaboration $ git pull Fast-forward… "Updated submodules" $ git submodule update --init 23 Plaçons-nous à présent dans le cas d'un clone du dépôt sur lequel nous venons de propager des modifications, qui n'a plus été mis à jour depuis longtemps. L'utilisation d'un pull mettra à jour la liste des sous-modules, et invalidera éventuellement les versions de certains sous-modules… mais ne les mettra pas à jour automatiquement ! Après la mise à jour du pointeur vers le commit souhaité du sous-module, pour mettre à jour le contenu du sous-module lui-même, il faut utiliser submodule update, qui effectuera un pull en cas de besoin, suivi d'une mise à jour du contenu au nouveau commit indiqué. Néanmoins, cela n'est pas suffisant en cas d'ajout d'un nouveau sous-module. Dans cette situation, un "submodule init" est nécessaire… ou l'utilisation de l'option "--init", qui appellera "submodule init" au besoin. Enfin, comme précédemment, pour que les sous-modules imbriqués soient eux aussi mis à jour et initialisés au besoin, on utilisera l'option "--recursive". En réalité, une fois les sous-modules faisant partie du mode de travail habituel, la commande de mise à jour du dépôt passe généralement de "git pull" à ¬ "git pull && git submodule update --init --recursive", cette dernière commande étant neutre en l'absence de modifications.

Slide 121

Slide 121 text

Collaboration $ git pull Fast-forward… "Updated submodules" $ git submodule update --init --recursive 23 Plaçons-nous à présent dans le cas d'un clone du dépôt sur lequel nous venons de propager des modifications, qui n'a plus été mis à jour depuis longtemps. L'utilisation d'un pull mettra à jour la liste des sous-modules, et invalidera éventuellement les versions de certains sous-modules… mais ne les mettra pas à jour automatiquement ! Après la mise à jour du pointeur vers le commit souhaité du sous-module, pour mettre à jour le contenu du sous-module lui-même, il faut utiliser submodule update, qui effectuera un pull en cas de besoin, suivi d'une mise à jour du contenu au nouveau commit indiqué. Néanmoins, cela n'est pas suffisant en cas d'ajout d'un nouveau sous-module. Dans cette situation, un "submodule init" est nécessaire… ou l'utilisation de l'option "--init", qui appellera "submodule init" au besoin. Enfin, comme précédemment, pour que les sous-modules imbriqués soient eux aussi mis à jour et initialisés au besoin, on utilisera l'option "--recursive". En réalité, une fois les sous-modules faisant partie du mode de travail habituel, la commande de mise à jour du dépôt passe généralement de "git pull" à ¬ "git pull && git submodule update --init --recursive", cette dernière commande étant neutre en l'absence de modifications.

Slide 122

Slide 122 text

Problèmes potentiels 24 L'utilisation des sous-modules est très puissante, mais peut poser quelques difficultés. Celles-ci sont faciles à surmonter si on les connaît. Tout d'abord, de par leur nature de “pointeur sur commit”, les sous-modules présents dans une seule branche ne sont pas reconnus par les autres… qui listent donc le dossier correspondant comme “untracked”. Il ne faut surtout pas ajouter ces fichiers dans une autre branche. Étant invisibles (car pointeur pur) dans une branche, et fichiers versionnés dans une autre, les conflits d'intégration seraient problématiques. Il n'y a pas de solution réelle en dehors d'intégrer rapidement la branche ayant ajouté le sous-module dans les autres. Également, nous avons vu “submodule add”, “submodule update”… et pourtant, “submodule rm” n'existe pas pour supprimer un sous-module. Actuellement, il n'existe pas d'autre moyen que la suppression manuelle, qui consiste à éditer les fichiers listant le sous-module avant de supprimer le contenu à proprement parler. Les fichiers en questions sont très lisibles (proches du YAML, format texte brut très propre), et leur édition ne devrait pas poser de difficulté majeure. De nombreuses ressources existent à ce sujet sur Internet en cas de besoin.

Slide 123

Slide 123 text

Problèmes potentiels • modules d'une branche “untracked” dans les autres 24 L'utilisation des sous-modules est très puissante, mais peut poser quelques difficultés. Celles-ci sont faciles à surmonter si on les connaît. Tout d'abord, de par leur nature de “pointeur sur commit”, les sous-modules présents dans une seule branche ne sont pas reconnus par les autres… qui listent donc le dossier correspondant comme “untracked”. Il ne faut surtout pas ajouter ces fichiers dans une autre branche. Étant invisibles (car pointeur pur) dans une branche, et fichiers versionnés dans une autre, les conflits d'intégration seraient problématiques. Il n'y a pas de solution réelle en dehors d'intégrer rapidement la branche ayant ajouté le sous-module dans les autres. Également, nous avons vu “submodule add”, “submodule update”… et pourtant, “submodule rm” n'existe pas pour supprimer un sous-module. Actuellement, il n'existe pas d'autre moyen que la suppression manuelle, qui consiste à éditer les fichiers listant le sous-module avant de supprimer le contenu à proprement parler. Les fichiers en questions sont très lisibles (proches du YAML, format texte brut très propre), et leur édition ne devrait pas poser de difficulté majeure. De nombreuses ressources existent à ce sujet sur Internet en cas de besoin.

Slide 124

Slide 124 text

Problèmes potentiels • modules d'une branche “untracked” dans les autres • git submodule rm n'existe pas •éditer .gitmodules •éditer .git/config • git rm --cached /path/to/module (sans slash final) 24 L'utilisation des sous-modules est très puissante, mais peut poser quelques difficultés. Celles-ci sont faciles à surmonter si on les connaît. Tout d'abord, de par leur nature de “pointeur sur commit”, les sous-modules présents dans une seule branche ne sont pas reconnus par les autres… qui listent donc le dossier correspondant comme “untracked”. Il ne faut surtout pas ajouter ces fichiers dans une autre branche. Étant invisibles (car pointeur pur) dans une branche, et fichiers versionnés dans une autre, les conflits d'intégration seraient problématiques. Il n'y a pas de solution réelle en dehors d'intégrer rapidement la branche ayant ajouté le sous-module dans les autres. Également, nous avons vu “submodule add”, “submodule update”… et pourtant, “submodule rm” n'existe pas pour supprimer un sous-module. Actuellement, il n'existe pas d'autre moyen que la suppression manuelle, qui consiste à éditer les fichiers listant le sous-module avant de supprimer le contenu à proprement parler. Les fichiers en questions sont très lisibles (proches du YAML, format texte brut très propre), et leur édition ne devrait pas poser de difficulté majeure. De nombreuses ressources existent à ce sujet sur Internet en cas de besoin.

Slide 125

Slide 125 text

Synthèse Nous allons à présent récapituler l'ensemble des stratégies vues à différentes échelles, et établirons leurs synergies pour aboutir à un ensemble de règles cohérent et efficace.

Slide 126

Slide 126 text

26 La plus petite entité d'un système de gestion de versions est le commit. Celui-ci devrait être atomique, c'est-à-dire que chacun d'entre eux ne doit représenter qu'une seule modification fonctionnelle. Cette modification peut bien entendu concerner de nombreux fichiers et lignes de code ; mais plus l'impact individuel de chaque commit sera limité, plus l'isolation de régressions sera facilitée. Le message associé au commit devrait décrire précisément l'impact au niveau fonctionnel. Lister les fichiers modifiés n'a aucun intérêt, cette liste étant de toute façon accessible dans l'historique. À l'échelle des branches, l'utilisation des "feature branches" devrait être systématique, accompagnée de la garantie de déployabilité de la branche master. Une branche correctement intégrée devrait donner lieu à l'étiquetage de master par un numéro de version SemVer, c'est-à-dire explicitant le contrat passé avec les clients de l'API fournie par le projet. Si ces conventions sont respectées, la décomposition et la réutilisation de projets par le mécanisme des sous-modules devient simple, et même rassurante : tout module sur master et dont le numéro de version majeur est fixe est, par définition même, fiable. Une fois tous ces éléments mis en place, le code résultant sera bien plus modularisé, réutilisable, et l'isolation de bugs sera très fortement simplifiée, tous points améliorant la qualité, la maintenabilité et la valeur du projet.

Slide 127

Slide 127 text

26 commits atomiques 1 modification = 1 commit La plus petite entité d'un système de gestion de versions est le commit. Celui-ci devrait être atomique, c'est-à-dire que chacun d'entre eux ne doit représenter qu'une seule modification fonctionnelle. Cette modification peut bien entendu concerner de nombreux fichiers et lignes de code ; mais plus l'impact individuel de chaque commit sera limité, plus l'isolation de régressions sera facilitée. Le message associé au commit devrait décrire précisément l'impact au niveau fonctionnel. Lister les fichiers modifiés n'a aucun intérêt, cette liste étant de toute façon accessible dans l'historique. À l'échelle des branches, l'utilisation des "feature branches" devrait être systématique, accompagnée de la garantie de déployabilité de la branche master. Une branche correctement intégrée devrait donner lieu à l'étiquetage de master par un numéro de version SemVer, c'est-à-dire explicitant le contrat passé avec les clients de l'API fournie par le projet. Si ces conventions sont respectées, la décomposition et la réutilisation de projets par le mécanisme des sous-modules devient simple, et même rassurante : tout module sur master et dont le numéro de version majeur est fixe est, par définition même, fiable. Une fois tous ces éléments mis en place, le code résultant sera bien plus modularisé, réutilisable, et l'isolation de bugs sera très fortement simplifiée, tous points améliorant la qualité, la maintenabilité et la valeur du projet.

Slide 128

Slide 128 text

26 branches isolées 1 fonctionnalité = 1 branche branche master toujours déployable commits atomiques 1 modification = 1 commit La plus petite entité d'un système de gestion de versions est le commit. Celui-ci devrait être atomique, c'est-à-dire que chacun d'entre eux ne doit représenter qu'une seule modification fonctionnelle. Cette modification peut bien entendu concerner de nombreux fichiers et lignes de code ; mais plus l'impact individuel de chaque commit sera limité, plus l'isolation de régressions sera facilitée. Le message associé au commit devrait décrire précisément l'impact au niveau fonctionnel. Lister les fichiers modifiés n'a aucun intérêt, cette liste étant de toute façon accessible dans l'historique. À l'échelle des branches, l'utilisation des "feature branches" devrait être systématique, accompagnée de la garantie de déployabilité de la branche master. Une branche correctement intégrée devrait donner lieu à l'étiquetage de master par un numéro de version SemVer, c'est-à-dire explicitant le contrat passé avec les clients de l'API fournie par le projet. Si ces conventions sont respectées, la décomposition et la réutilisation de projets par le mécanisme des sous-modules devient simple, et même rassurante : tout module sur master et dont le numéro de version majeur est fixe est, par définition même, fiable. Une fois tous ces éléments mis en place, le code résultant sera bien plus modularisé, réutilisable, et l'isolation de bugs sera très fortement simplifiée, tous points améliorant la qualité, la maintenabilité et la valeur du projet.

Slide 129

Slide 129 text

26 branches isolées 1 fonctionnalité = 1 branche branche master toujours déployable commits atomiques 1 modification = 1 commit versions sémantiques 1 API publique garantie = 1 version API publique toujours documentée La plus petite entité d'un système de gestion de versions est le commit. Celui-ci devrait être atomique, c'est-à-dire que chacun d'entre eux ne doit représenter qu'une seule modification fonctionnelle. Cette modification peut bien entendu concerner de nombreux fichiers et lignes de code ; mais plus l'impact individuel de chaque commit sera limité, plus l'isolation de régressions sera facilitée. Le message associé au commit devrait décrire précisément l'impact au niveau fonctionnel. Lister les fichiers modifiés n'a aucun intérêt, cette liste étant de toute façon accessible dans l'historique. À l'échelle des branches, l'utilisation des "feature branches" devrait être systématique, accompagnée de la garantie de déployabilité de la branche master. Une branche correctement intégrée devrait donner lieu à l'étiquetage de master par un numéro de version SemVer, c'est-à-dire explicitant le contrat passé avec les clients de l'API fournie par le projet. Si ces conventions sont respectées, la décomposition et la réutilisation de projets par le mécanisme des sous-modules devient simple, et même rassurante : tout module sur master et dont le numéro de version majeur est fixe est, par définition même, fiable. Une fois tous ces éléments mis en place, le code résultant sera bien plus modularisé, réutilisable, et l'isolation de bugs sera très fortement simplifiée, tous points améliorant la qualité, la maintenabilité et la valeur du projet.

Slide 130

Slide 130 text

26 branches isolées 1 fonctionnalité = 1 branche branche master toujours déployable commits atomiques 1 modification = 1 commit versions sémantiques 1 API publique garantie = 1 version API publique toujours documentée modules découplés 1 bibliothèque = 1 module La plus petite entité d'un système de gestion de versions est le commit. Celui-ci devrait être atomique, c'est-à-dire que chacun d'entre eux ne doit représenter qu'une seule modification fonctionnelle. Cette modification peut bien entendu concerner de nombreux fichiers et lignes de code ; mais plus l'impact individuel de chaque commit sera limité, plus l'isolation de régressions sera facilitée. Le message associé au commit devrait décrire précisément l'impact au niveau fonctionnel. Lister les fichiers modifiés n'a aucun intérêt, cette liste étant de toute façon accessible dans l'historique. À l'échelle des branches, l'utilisation des "feature branches" devrait être systématique, accompagnée de la garantie de déployabilité de la branche master. Une branche correctement intégrée devrait donner lieu à l'étiquetage de master par un numéro de version SemVer, c'est-à-dire explicitant le contrat passé avec les clients de l'API fournie par le projet. Si ces conventions sont respectées, la décomposition et la réutilisation de projets par le mécanisme des sous-modules devient simple, et même rassurante : tout module sur master et dont le numéro de version majeur est fixe est, par définition même, fiable. Une fois tous ces éléments mis en place, le code résultant sera bien plus modularisé, réutilisable, et l'isolation de bugs sera très fortement simplifiée, tous points améliorant la qualité, la maintenabilité et la valeur du projet.

Slide 131

Slide 131 text

Prochaines sessions 1. Introduction 2. Stratégies 27

Slide 132

Slide 132 text

Prochaines sessions 1. Introduction 2. Stratégies 3. Usage intermédiaire 27

Slide 133

Slide 133 text

Prochaines sessions 1. Introduction 2. Stratégies 3. Usage intermédiaire 4. Usage avancé 27

Slide 134

Slide 134 text

Merci ! Des questions ? • Ressources • SemVer : semver.org • Git-flow • GitHub Flow • Les limites des feature branches • Manipulation des sous-modules • Outils • git-flow plugin : github.com/nvie/gitflow • Images • Logo Git par Alex Bargi • Cible, Shuffle, Panneau, Bulle, Réseau, Médaille, Trophée CC-BY TheNounProject.com • Serveur, écran © Apple • Remerciements • Scott Chacon (@chacon) • Vincent Driessen (@nvie) • Fabien Massol • Yann Prosper • Eurogiciel 28 Git-flow : http://nvie.com/posts/a-successful-git-branching-model/, http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/ GitHub Flow : http://scottchacon.com/2011/08/31/github-flow.html Les limites des feature branches : http://www.youtube.com/watch?v=xzstASOvqNc Manipulation des sous-modules : http://chrisjean.com/2009/04/20/git-submodules-adding-using-removing-and-updating/