Important

Attention, les captures d’écran faites sur GitLab proviennent d’une ancienne version de la forgeMIA. Cela ne devrait pas géner la compréhension et la bonne lecture des supports.

Les supports seront mis à jour au moment du passage à la forge institutionnelle.

Objectifs

Découvrir :

  • Les branches
  • Principe “issue + MR + branche”
  • Fusion (merge)
  • Rebasage

Rappels

Rappels de la session 1

Nous avons vu :

  • l’intérêt de l’usage d’un outil comme git
  • les différents états d’un dépôt local
  • les commandes principales selon 3 modes
    • en ligne de commande
    • avec RStudio
    • avec VS Code

Rappels de la session 2

Nous avons vu :

  • GitLab : accès, configuration et fonctionnalités
  • dépôt distant
  • bonnes pratiques d’interaction

Cas d’utilisation des branches

Conditions d’usage des branches

  • s’assurer que la branche main est toujours stable (i.e. fonctionnelle)
  • les branches sont créées à partir de main

Utilité des branches

  • Ne pas mélanger ses développements en cours
  • Programmer en parallèle des collègues
  • Faire des tests et expérimentations
  • Laisser un travail en cours pour un autre plus urgent
    • Résolution de bug
    • Développement de fonctionnalité

Pratique non idéale

Sur une seule branche :

  • Du développement
  • Du débogage
  • Du test

Et le tout en même temps !

Principes des branches

Définition d’une branche

  • Une branche est une copie isolée du code du projet.
  • Le travail dans une branche n’affecte pas les autres.
  • Permet d’avoir un historique non linéaire des commits.

Utilisation d’une branche

Scénario classique :

  • Partir d’une branche stable (typiquement main ou master)
  • Créer une nouvelle branche
  • Résoudre un problème sur cette branche :
    • Nouvelle fonctionnalité
    • Résolution de bugs
    • Tests de code/prototypage
  • Une fois le problème résolu, fusionner la nouvelle branche dans la branche stable

Exemple à suivre (1)

Les fonctionnalités évoluent dans des branches séparées

Exemple à suivre (2)

Fusion (merge) avec main

L’exemple précédent fonctionne si :

  • il n’y a pas de modifications sur main
  • il n’y a pas un même fichier modifié sur chacune des branches

Sinon, il est nécessaire de faire un rebasage.

Scénario facile

Il n’est pas de nécessaire de faire un rebasage.

Chaque branche est construite à partir de la branche main.

Scénario “Rebasage nécessaire”

Ici on ne pourra pas faire un merge de la branche Fonction-2 avant son rebasage.

# On se place sur la branche sur laquelle on souhaite rebaser
git branch Fonction-2
# On "rebase" la branche principale main sur la branche Fonction-2
git rebase main

Principes de la fusion

  • Lorsqu’on a travaillé sur une branche, il faut la fusionner dans la branche dite stable (main ou master)
  • Cette opération s’appelle une fusion puisqu’elle va consister à intégrer le code nouveau de la branche, dans la branche stable
  • Suite à un push d’une mise à jour de branche, il faut demander une fusion (Merge request dans GitLab)
  • GitLab va vérifier que la fusion est possible, et l’autoriser le cas échéant
  • Ou inviter à résoudre les conflits (deux modifications au même endroit dans un même fichier)

Pratique

Récupération du projet et exploration de son contenu

  • Récupération du dépôt : récupérer le dépôt de votre voisin
  • Celui-ci doit vous inviter dans son projet sur GitLab
  • Essayer de modifier des fichiers différents
  • Le même fichier à des endroits différents
  • Le même fichier sur la même ligne
  • Faites de scommits et des push
  • QUe se passe-t-il?

Gestion des branches avec GitLab

Dans GitLab :

On peut :

  • visualiser la liste des branches
  • visualiser le dépôt pour une branche
  • supprimer une branche
  • déclencher des “merge request” ou “requête de fusion”

Visualiser les branches

Visualiser le dépôt d’une branche

Cliquez sur le nom d’une branche pour voir le dépôt dans l’état correspondant

Création d’une branche (1/3)

Via une issue

Création d’une branche (2/3)

Via le menu branche

Création d’une branche (3/3)

Avec ces méthodes de création d’une branche depuis GitLab, il faut récupérer la nouvelle branche en local.

# Lister toutes les branches disponibles (locales et distantes)
git branch -a
# Récupérer le contenu de la branche
git pull origin la_branche_distante
# se mettre dessus
git switch la_branche_distante

Un git pull dans RStudio et VS Code permet de récupérer automatiquement la branche dans l’IDE.

Note

Nous conseillons de passer par une issue pour créer une branche (parce que tout part d’une idée et que l’on veut en garder une trace, même lorsque l’on travaille seul!)

Pratique

D’une issue à une branche

  1. Créer une nouvelle issue.
  2. Choisissez un modèle de description parmi ceux proposés.
  3. À partir de cette issue, créer une nouvelle branche.
  4. Faites un pull sur votre machine.
  5. Observer la nouvelle branche.

On s’arrête là pour le moment !

Gestion des branches locales

RStudio

Créer une nouvelle branche

Pour importer une branche créée depuis GitLab

git pull ou en cliquant sur le bouton pull de RStudio.

À partir d’une étiquette existante

En ligne de commande (dans le terminal RStudio) :

git checkout -b nom_de_ma_branche v2.9.1

Cette commande permet de crée une branche nom_de_ma_branche à partir de l’étiquette v2.9.1 et bascule sur celle-ci.

Lister les branches (1/2)

Lister les branches (2/2)

Ou via la fenêtre de commit

Supprimer une branche

(dans le terminal de RStudio)

# pour visualiser les branches locales
git branch
# pour supprimer les branches locales
git branch -d nom_de_ma_branche
# pour visualiser les branches restantes
git branch

En ligne de commande

Création

Pour créer une branche depuis git-2.23 (août 2019)

# Création de la branche patch-1
git branch patch-1
# Basculer sur la branche patch-1
git switch patch-1
# Basculer si switch n'est pas disponible
git checkout patch-1
# Ou en raccourci
git switch -c patch-1

Création à partir d’une étiquette existante

La commande suivante :

git checkout -b patch-1 v2.9.1

permet de :

  • créer une branche patch-1 à partir de l’étiquette v2.9.1
  • et bascule dessus.

Lister les branches

git branch
  main
* patch-1

NB : l’historique affiche le nom des branches

git log --oneline --decorate
e82b921 (HEAD -> patch-1, tag: v2.9.1, main) init

Supprimer une branche locale

# supprimer une branche totalement fusionnée (-d ou --delete)
git branch --delete patch-1
# supprimer une branche (même non fusionnée)
git branch -D patch-1

Travailler avec plusieurs branches simultanément

Basculer d’une branche à une autre

# connaître la branche en cours
git branch

# Naviguer parmis les branches
git checkout main
git checkout patch-1
git checkout patch-2
# ou depuis git-2.23
git switch patch-1
git switch - # bascule sur la précédente branche (patch-1 ici)

# montrer l’historique de la branche
git log patch-1
# montrer l’historique de toutes les branches
git log --all

Avec VS Code

Interface

Création

  • crée une branche nommée patch-1
  • bascule dessus

À partir d’une étiquette existante (1/2)

  • Créer une étiquette v2.9.1

À partir d’une étiquette existante (2/2)

  • Clic sur la branche en cours
  • Menu “Create branch from …”
  • Sélection de l’étiquette v2.9.1
  • Nommage de la nouvelle branche patch-1
  • Bascule dessus automatiquement

Lister les branches

Supprimer une branche locale

  • sélectionner la branche à supprimer
  • la branche en cours ne peut être supprimée

Travailler avec plusieurs branches simultanément

Basculer d’une branche à une autre

Gestion des branches distantes

Il n’est pas possible de gérer les branches distantes via RStudio, il faudra passer par les lignes de commandes.

En ligne de commande

Récupérer une branche distante

# Récupérer une branche distante :
git fetch
git switch patch-1

# Récupérer les modifications de la branche distante :
git pull
# Envoyer les modifications sur la branche distante :
git push origin patch-1

avec origin l’alias du dépôt distant (par défaut).

NB : possibilité de renommer la branche.

Supprimer une branche distante

# Supprimer une branche distante
git push -d origin remote-patch-1

avec origin l’alias du dépôt distant (par défaut).

Dans quelle branche suis-je ?

git status
On branch local-patch-1
Your branch is up to date with 'origin/remote-patch-1'.

Conseil

  • Après une commande sur les branches, pensez à vérifier que vous êtes bien en train de coder sur la branche dans laquelle vous pensez être…
  • git status : vous donnera toujours la bonne information.

Quelles sont les branches ?

# Lister les branches locales
git branch
# Lister aussi les branches distantes
git branch -a

Avec VS Code

Récupérer une branche distante :

Récupérer les modifications de la branche distante :

Synchroniser les modifications locales avec celles distantes

Envoyer les modifications sur la branche distante :

L’icône identifiée apparaît tant que la branche locale n’existe pas sur le serveur distant.

Supprimer une branche distante

Impossible de faire cela avec l’interface VS code.

Il est nécessaire de passer par la ligne de commande, dans le terminal.

git push -d origin remote-patch-1

Dans quelle branche suis-je ?

Quelles sont les branches ?

Pratique

gérer la branche

  1. basculer sur votre branche créée précédemment
  2. la publier sur le dépôt distant
  3. parcourir la nouvelle branche dans GitLab
  4. faites le ménage
    1. supprimer la branche locale et distante
    2. supprimer le ticket

Fusion, conflit, remisage

Le merge request (MR)

Définition

Le merge request est une requête de fusion spécifique à GitLab qui vise à incorporer des changements d’une branche spécifique dans la branche principale (main).

Fusion de hotfix sur main puis de issue-1 sur main

Démo dans GitLab

GitLab permet de simplifier les étapes :

  • Nous avons vu :
    1. Créer une issue
    2. Créer une requête de fusion avec une branche depuis chaque issue
    3. Récupérer la branche en local
    4. Faire les modifications, valider, pousser
  • Le formateur réalise la fusion :
    1. accepter la requête de fusion
    2. déclencher la fusion
    3. parcourir la branche main et constater les modifications

Dans les faits, GitLab facilite le merge request.

Apparition et gestion des conflits

En cas de modifications différentes de la même partie du même fichier dans les deux branches, Git ne sera pas capable de réaliser proprement la fusion.

Git ajoute des marques de conflit standards dans les fichiers qui comportent des conflits, pour que vous puissiez les ouvrir et résoudre les conflits manuellement.

Votre fichier avec conflit contient des sections qui ressemblent à ceci :

<<<<<<< HEAD:patch-1
<div id="footer">contact : email.support@github.com</div>
======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> patch-1:index.html

Résolution du conflit

  1. Visualiser les conflits : git status
  2. Identifier le conflit : le conflit est compris entre les signes <<<<<<< et >>>>>>>
<<<<<<< HEAD:patch-1
<div id="footer">contact : email.support@github.com</div>
======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> patch-1:index.html
  1. Visualiser les différences :
    • le signe ====== correspond au “centre” du conflit
    • le centre permet de comparer la version initiale de la version qu’on souhaite fusionner
    • tout ce qui est au dessus du centre est la version présente sur la branche sur laquelle on souhaite faire la fusion
    • tout ce qui est en dessous du centre est la version qu’on souhaite fusionner.
  1. Résoudre le conflit :
    • Modifier le fichier concerné par le conflit avec son éditeur de texte (option à privilégier)
    • N’oubliez pas de bien supprimer toutes les informations générées par le conflit

Conseil

Prenez votre temps au moment de la résolution de conflit !

Remisage

Dans le cas où :

  • un travail est en cours, instable
  • il n’est pas en état d’être validé (commit)
  • une autre modification est à faire, dans une autre branche

git stash enregistre dans la pile des modifications non finies que vous pouvez ré-appliquer à n’importe quel moment.

git status
vim mon_texte.txt
git status
git stash
git status
git stash list

Pour retrouver ses modifications : git stash apply.

Git remodifie les fichiers non validés lorsque la remise a été créée.

Une remise peut être appliquée sur une branche différente de celle où elle a été créée. Git vous indique les conflits de fusions si quoi que ce soit ne s’applique pas proprement.

git stash drop <nom de la remise> pour enlever une remise de la liste.

Bonnes pratiques de fusion

Si vous attendez trop longtemps pour fusionner deux branches qui divergent rapidement, vous rencontrerez des problèmes.

  • nombreux conflits à régler
  • risques accrus d’avoir à reprendre profondemment le code de votre branche pour la fusionner

Démo

Gestion d’un conflit

Le formateur crée une situation de conflit et la résoud.

Nettoyage

  • supprimer les fichiers non-suivis : git clean -f.
  • supprimer les fichiers non-suivis et dossiers vides non suivis : git clean -f -d
  • supprimer aussi les fichiers correspondant à .gitignore : git clean -f -x

Pour plus d’information sur le remisage et le nettoyage : https://git-scm.com/book/fr/v2/Utilitaires-Git-Remisage-et-nettoyage

Rebasage

Rebasage

Définition

Permet de modifier l’origine d’une branche.

Utilité

  • Rester à jour avec les modifications faites sur la branche d’origine
  • Permet de maintenir un historique de projet “linéaire”
  • Facilite les merge

Illustration du besoin de rebasage

Problème : les modifications apportées par le 1er merge ne sont pas intégrées à la branche Fonction-2 avant de la fusionner dans main

Faire un rebasage en ligne de commande

Rebaser la branche Fonction-2 sur main après le merge de Bug-fonction-1 :

# On s'imagine qu'on vient de faire le merge de Bug-fonction-1 sur main
# Par sécurité on s'assure que main est à jour avec le serveur
git switch main
git pull
# On passe sur Fonction-2
git switch Fonction-2
git rebase main

Rebasage dans GitLab

Peut se faire dans GitLab dans la requête de fusion

Résultat

On constate qu’on a modifié l’historique pour le rendre linéaire

Inconvénient

Important

Le rebasage réécrit l’historique des commits

Cela peut engendrer des problèmes si d’autres développeurs travaillent sur la même branche en même temps

Recommandations

De préférence, rebaser uniquement des branches :

  • Sur lequelles on travaille seul
  • Pour lesquelles on peut prévenir les autres développeurs de la réalisation d’un rebasage

Pratique

Rebasage

  1. ouverture de l’issue
  2. échange éventuel de commentaires
  3. création d’une MR et d’une branche sur la forge
  4. option: possibilité d’ajouter un voisin en reviewer du travail qui sera fait
  5. récupération de la nouvelle branche (distante), en local
  6. Correction de l’erreur dans le fichier texte en question
  7. éventuellement dialogue avec celui qui a signalé l’issue
  8. commit
  9. push
  10. connexion à la forge
  11. activation de la requête de fusion
  12. rebasage sur GitLab
  13. pull pour récupérer la branche mise à jour
  14. poursuite de la fusion

Bonnes pratiques pour les branches

  • Ne pas faire de commit sur la branche main !
  • git status au début d’une séquence de travail pour vérifier sur quelle branche on est
  • git pull pour récupérer d’éventuels commit
  • Créer une branche pour chaque bug ou évolution
  • Toujours créer une branche à partir du tronc (main ou master)
  • Avant de changer de branche, commit ou stash (bien nommés)
  • Ne pas trainer pour fusionner

Pour aller plus loin

Quelques ressources Git et GitLab

Gestion de projet avec les branches

Deux grandes manières d’utiliser des branches :

Merge request (gitflow)

Un mode d’utilisation des branches basé sur un scénario “gitflow”

  • Faire du merge request vers la branche dev
  • Puis merge request de dev vers main
  • A l’issue des merges, supprimer les branches (locales et distantes) sources

Prochaine session