Git GitLab EE

Commit / Merge / Rebase / Workflow / Squash 

Ordre du jour

• Intro

• Merge / rebase

• Workflow

• Rebase onto

• Rebase interactif et Squash

• Bonnes pratiques

• Conclusion                                   

Le but de ce point est de parler GIT, certaines de ses principales notions et du Workflow à adopter.

Construire ensemble le workflow de demain !

Définition de Git

 

Svn vs Git

 

Définition de repository / Working Area/Staging Area

 

Définition de local repository / remote repository

Ce qui ne va pas être abordé dans cette présentation !

Concepts

Basiques 

Le commit !

Le commit est l'unité de base de Git pour construire une chronologie d'un projet.

Définition

Le commit !

Le commit est l'unité de base de Git pour construire une chronologie d'un projet.

Définition

Un commit est considéré comme “Un Snapshot ou milestones” de l'état d'un projet Git.

Le commit !

Le commit est l'unité de base de Git pour construire une chronologie d'un projet.

Définition

Un commit est considéré comme “Un Snapshot ou milestones” de l'état d'un projet Git.

La  “notion du temps est primordiale” dans la définition d'un commit.

Commit anatomie 

sha1(
    commit date

    commit message

    committer

    author

    author date

    tree
)

Un commit = {} metadatas + project tree = un sha unique

La date du commit

Le message du commit

La personne qui commit

Le premier auteur du commit

Date de création du commit

Le tree de l'ensemble du projet

Commit anatomie 

Un commit = {} metadatas + project tree = un sha unique

La date du commit

Le message du commit

La personne qui commit

Le premier auteur du commit

Date de création du commit

Le tree de l'ensemble du projet

sha1(
    commit date

    commit message

    committer

    author

    author date

    tree
)

Commit tree - Data Model

Merge & Rebase

Merge vs Rebase

Le but du merge est de fusionner les travaux de deux branches.

Le merge est une opération non-destructive, elle n'altère pas l'état des commits de la branche mergée.

Définition

Merge fast-forward - limites

//Avant                            |  //Après
A----B----C         (develop/HEAD) |  A----B----C----1----2 (develop/HEAD, project)
           \                       |                 
            1-----2  (project)     |              

Le merge est une opération polluante à cause du commit créé sur la branche cible !

Il existe principalement deux méthodes de merge

Merge no-fast-forward

//Avant                                  |  //Après
A----B----C----D----E     (develop/HEAD) |  A----B----C----D----E----F  (develop/HEAD)
                \                        |                  \       /
                 1-----2  (project)      |                   1-----2  (project)

Avantages

  • Commits avec SHA unique

  • Simple à revert un merge

  • Gestion simplifiée des conflits

  • Préserver l'historique

Inconvénients 

  • Pollution de l'historique

  • Effet guitare sur l'historique

Les + et - du merge

Le but du rebase est de changer la base d'une branche.

Le rebase est une opération destructive - elle altère l'état des commits de la branche rebasée.

Définition

Le rebase est une opération non-polluante  !

Il existe plusieurs méthodes de rebase. (Rebase sans paramètres, rebase interactif, rebase ontoetc.)

Exemple de rebase

//Avant                            | //Après
A----B----C----D    (develop/HEAD) | A----B----C----D----$1----$2  (develop/HEAD,project)
           \                       |                   
            1---- 2 (project)      |

L'opération du rebase est souvent utilisée pour nettoyer l'historique des branches Git pour le rendre linéaire afin d'avoir une meilleure lisibilité.

$: indique le changement de SHA des commits.

Avantages

  • Rejouer les commit un par un

  • Modifier/supprimer des commit en cours du rebase

  • Aucune pollution de l'historique

  • Historique linéaire et lisible

  • Incite les contributeurs à nettoyer assez souvent l'historique des branches avant de les merge

Inconvénients 

  • Modifie les SHA des commits

  • Difficile de revert un rebase

  • Le push force après rebase

Les + et - du rebase

merge vs rebase

 

En utilisant Git, la question qui se pose souvent à chaque début de projet :

Devons-nous fonctionner avec des merges ou des rebases ?

La réponse n'est surtout pas booléenne !

Il n'existe pas de solution magique adaptée à toutes les situations.

Ce qui peut aider à prendre une décision :

  • L'historique Git doit être concis, claire et facilement lisible !

  • Les pratiques doivent être homogènes au sein d'une équipe

  • Définir et suivre les règles du workflow de contribution

La Gestion de L'historique GIT
N'est pas
Importante

La Gestion de L'historique GIT
N'est pas
Est très Importante

À garder à l'esprit que l'historique Git est une forme de documentation technique du code.

Note!

Notre nouveau
Workflow Git

La définition d'un Workflow Git unique, pour l'ensemble des contributeurs, est indispensable pour garantir une meilleure collaboration et installer

des règles de contribution identiques pour tous

  • Les commits directs sur la branche master sont interdits

  • Les push force sur master sont désormais bloqués

  • L'utilisation des MR est obligatoire

  • Les rebase sont obligatoires avant d'accepter toute MR

  • Tous les merge sont en (--no-ff), sauf le merge de develop sur master

  • Seule la branche develop peut être merge sur master (en ff)

  • La branche develop est rebase sur master à chaque release - cf. process de release

Les lignes directives du workflow

  • Les branches projet sont créées à partir de develop

  • Les branches feature sont créées à partir des branches projet

  • Le premier commit sur la branche projet  doit être facilement repérable et identifiable. (souvent, c'est celui du changement de version) !

  • Nouvelles règles de nommage des branches - cf. doc.

  • Nouvelle sémantique des messages des commits - cf. doc

Les lignes directives du workflow

Utilisation des MR

  1. Lors du merge des travaux d'une branche feature avec la branche projet

  2. Lors du merge d'une sous-branche d'un projet avec la branche projet

  3. Lors du merge de la branche projet avec la branche develop

  4. Lors du merge d'une branche mco (ou toute autre branche de maintenance) avec la branche develop

  5. Lors du merge d'une branche hotFix avec la branche develop

Les lignes directives du workflow

La MR ne doit pas être accepté par le contributeur qui la créé.

Dans le nouveau GitLab EE, il ne sera pas possible d'accepter une MR si la branche source n'est pas rebase sur la branche destinataire.

Utilisation des merge & rebase 

Les lignes directives du workflow

  1. Les deux méthodes, merge et rebase, seront utilisées dans notre workflow

  2. À chaque MR, un rebase est effectué suivi d'un merge

  3. Les rebase & merge, dans le cadre d'une MR, sont effectués via l'interface

  4. Le contributeur effectue un rebase localement seulement si GitLab n'arrive pas à rebase automatiquement.

  5. Le rebase de develop sur master ne doit pas se faire via l'interface (suivre le process de release)

Dans le nouveau GitLab EE, le merge et rebase, lors d'une MR, seront effectués automatiquement via l'UI.

GitLab EE donne la main au contributeur s'il n'arrive pas à prendre une décision et/ou résoudre des conflits.

Quelques exemples !

Merge - Rebase / master - develop - feat

 Workflow branche feat -> projet

Comment merge* la branche feature avec project ?

* Le merge doit passer par une MR

Cas 1         

Cas 2

 Workflow branche feat -> projet

Cas 1         

Cas 2

 Workflow branche feat -> projet

 Workflow branche feat -> projet

merge sans rebase

rebase avant merge(--no-ff)

Workflow branche projet -> develop

Comment merge* la branche project avec develop ?

* Le merge doit passer par une MR

Cas 1         

Cas 2

Workflow branche projet -> develop

Cas 1         

Cas 2

Workflow branche projet -> develop

Cas 1         

Cas 2

Workflow branche projet -> develop

Cas 1         

Cas 2

Workflow branche projet -> develop

merge sans rebase

rebase avant merge (--no-ff)

Workflow branche projet -> develop

 Workflow branche develop -> master

Comment merge* la branche develop avec master ?

* Le merge ne doit pas passer par une MR

 Workflow branche develop -> master

Cas 1         

Cas 2

Cas 3

Cas 1         

Cas 2

Cas 3

 Workflow branche develop -> master

Cas 1         

Cas 2

Cas 3

 Workflow branche develop -> master

Cas 1         

Cas 2

Cas 3

 Workflow branche develop -> master

Cas 1         

Cas 2

Cas 3

 Workflow branche develop -> master

merge sans rebase

rebase avant merge (--ff)

rebase avant merge (--no-ff)

 Workflow branche develop -> master

Rebase --onto

Mieux maitriser son rebase !

Le rebase --onto facilite les rebase, même les plus complexes, sans subir les conséquences d'un rebase standard.

 

Il offre également une certaine souplesse dans la réorganisation des commits (supprimer, renommer, réordonner...etc.)

 Définition

Dans certaines situations et avec une compréhension ambiguë du concept, l'action du rebase peut s'avérer complexe à réaliser.

Exemple

//État initial                             
A----B----C                          (master/ HEAD) 
      \                                    
       D---...---Y---Z               (develop/HEAD)
                  \                        
                   1---2---3         (project/HEAD)

 Situation

Dans certaines situations et avec une compréhension ambiguë du concept, l'action du rebase peut s'avérer complexe à réaliser.

Exemple

//État initial                             
A----B----C                          (master/ HEAD) 
      \                                    
       D---...---Y---Z               (develop/HEAD)
                  \                        
                   1---2---3         (project/HEAD)

$: indique le changement de SHA des commits.

 Situation

//Rebase develop sur master
A----B----C                          (master/HEAD)
           \                                               
            $D---...---$Y---$Z       (develop/HEAD)
                   x                 (/Ce lien est perdu*/)
                    1---2---3        (project/HEAD)

Dans certaines situations et avec une compréhension ambiguë du concept, l'action du rebase peut s'avérer complexe à réaliser.

Exemple

//État initial                             
A----B----C                          (master/ HEAD) 
      \                                    
       D---...---Y---Z               (develop/HEAD)
                  \                        
                   1---2---3         (project/HEAD)

$: indique le changement de SHA des commits.

 Situation

//Rebase develop sur master
A----B----C                          (master/HEAD)
           \                                               
            $D---...---$Y---$Z       (develop/HEAD)
                   x                 (/Ce lien est perdu*/)
                    1---2---3        (project/HEAD)
//Rebase project sur develop (sans rebase --onto)
A----B----C                          (master/HEAD)
           \
            $D---...---$Y---$Z       (develop/HEAD)
      ...\...                        (Chercher le plus ancien parent commun pour rebase*/)
                         1----2---3  (project/HEAD)

Syntaxe du rebase --onto 

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Syntaxe du rebase --onto 

//Avant                              |  //Après
A----B----C----D     (develop)       |  A----B----C----D            (develop)
           \                         |                  \    
            1----2   (project/HEAD)  |                   $1----$2   (project/HEAD)

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 1 - Rebase onto standard

$: indique le changement de SHA des commits.

Syntaxe du rebase --onto 

$ git checkout project
$ git rebase --onto D C

//Avant                              |  //Après
A----B----C----D     (develop)       |  A----B----C----D            (develop)
           \                         |                  \    
            1----2   (project/HEAD)  |                   $1----$2   (project/HEAD)

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 1 - Rebase onto standard

$: indique le changement de SHA des commits.

Syntaxe du rebase --onto 

$ git checkout project
$ git rebase --onto D C
 
//Avant                              |  //Après
A----B----C----D     (develop)       |  A----B----C----D            (develop)
           \                         |                  \    
            1----2   (project/HEAD)  |                   $1----$2   (project/HEAD)

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 1 - Rebase onto standard

//Avant                                  |  //Après
A----B----C----D----E    (develop)       |  A----B----C----D----E       (develop)
      \                                  |                  \    
       1----2----3----4  (project/HEAD)  |                   $3----$4   (project/HEAD)

Exemple 2 - Rebase onto avec suppression de commits

$: indique le changement de SHA des commits.

Syntaxe du rebase --onto 

$ git checkout project
$ git rebase --onto D C
 
//Avant                              |  //Après
A----B----C----D     (develop)       |  A----B----C----D            (develop)
           \                         |                  \    
            1----2   (project/HEAD)  |                   $1----$2   (project/HEAD)

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 1 - Rebase onto standard

$ git checkout project
$ git rebase --onto D 2

//Avant                                  |  //Après
A----B----C----D----E    (develop)       |  A----B----C----D----E       (develop)
      \                                  |                  \    
       1----2----3----4  (project/HEAD)  |                   $3----$4   (project/HEAD)

Exemple 2 - Rebase onto avec suppression de commits

$: indique le changement de SHA des commits.

Syntaxe du rebase --onto 

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 3 - Situation abordée précédemment 

$: indique le changement de SHA des commits.

//Rebase project sur develop (sans rebase --onto)
A----B----C                          (master/HEAD)
           \
            $D---...---$Y---$Z       (develop/HEAD)
      ...\...                        (Chercher le plus ancien parent commun pour rebase*/)
                         1----2---3  (project/HEAD)
//Rebase onto project sur develop
A----B----C                                  (master/HEAD)
           \
            $D---...---$Y---$Z               (develop/HEAD)
                              \
                               $1----$2---$3  (project/HEAD)

Exemple 3 - Solution

Syntaxe du rebase --onto 

git rebase --onto <newparent> <oldparent> <feature-branch/until>

Exemple 3 - Situation abordée précédemment 

$: indique le changement de SHA des commits.

//Rebase project sur develop (sans rebase --onto)
A----B----C                          (master/HEAD)
           \
            $D---...---$Y---$Z       (develop/HEAD)
      ...\...                        (Chercher le plus ancien parent commun pour rebase*/)
                         1----2---3  (project/HEAD)
$ git checkout project
$ git rebase --onto $Z CURRENT_PARENT (ou $git rebase --onto develop CURRENT_PARENT)

//Rebase onto project sur develop
A----B----C                                  (master/HEAD)
           \
            $D---...---$Y---$Z               (develop/HEAD)
                              \
                               $1----$2---$3  (project/HEAD)

Exemple 3 - Solution

CURRENT_PARENT: est le commit qui vient juste avant le premier commit de la branche project.

Les squash

Meld commits

Le squash consiste à regrouper n commits en 1 commit pertinent, compréhensible et cohérent.

 

Le but du squash est de rendre l'historique Git lisible, claire et pertinent.

 Définition

Exemple d'historique Git

* e0d1c94 - 2022-09-30 (14 seconds)- feat(metier) sql create report request OK !!! (HEAD -> master)
* db37fe2 - 2022-09-30 (62 seconds)- feat(metier) oups!!! update 2 sql create report request
* 4f5e97f - 2022-09-30 (2 minutes)- feat(metier) update sql create report request
* 683d34b - 2022-09-30 (2 minutes)- feat(metier) add sql create report request
* 9ff0e10 - 2021-03-24 (1 year, 6 months)- chore(master) add .gitignore regenerate-*.bat

 Situation

Lancer un rebase interactif (ou le faire sur IDE, autres outils..)

$ git rebase -i HEAD~4 (ou git rebase -i 9ff0e10)

Suivre les étapes indiquées - cf. doc.

Résultats

* 78fd32c - 2022-09-30 (2 minutes)- feat(metier) add sql create report request (HEAD -> master)
* 9ff0e10 - 2021-03-24 (1 year, 6 months)- chore(master) add .gitignore regenerate-*.bat

Les bonnes pratiques 

  1. Effectuer souvent des rebases des branches courantes

  2. Utiliser des messages de commit lisibles, cohérents et assez succincts  

  3. Réduire le nombre de commits

  4. Nettoyer l'historique Git des branches avant d'ouvrir des MRs

  5. Utiliser les squash

  6. Utiliser le rebase --onto

  7. Autres recommandations dans la future documentation

Certaines bonnes pratiques peuvent faciliter au quotidien la gestion du versioning des différents projets.

À noter

Questions ?

Si non, à vous de jouer !

R.O.T.I

Return On Time Invested

Évaluation, en temps réel, du retour sur le temps investi

Inutile : Une perte de temps, j'ai rien gagné, rien appris

Utile : Mais ça ne valait pas à 100% le temps investi

Moyen : Je n'ai pas perdu mon temps, sans plus !

Bon : J'ai gagné plus que le temps que j'y ai passé

Excellent : J'ai appris. Ça valait bien plus que le temps que j'y ai passé

Merci !

Lyes Chioukh

IT & IA Architect

Git/GitLab

By Lyes CHIOUKH

Git/GitLab

Plongez au cœur de Git et GitLab EE à travers une présentation synthétique qui allie théorie et retours d’expérience. Vous y découvrirez les bases indispensables du versioning, la différence entre merge et rebase, ainsi que leurs usages stratégiques dans un workflow collaboratif. Des techniques avancées comme le rebase --onto, le squash ou le rebase interactif sont présentées pour aider à maintenir un historique propre et pertinent. L’accent est mis sur des règles claires, des pratiques homogènes et une gestion efficace des branches pour fluidifier le travail en équipe. Ce contenu, volontairement condensé, laisse de côté certaines notions plus poussées qui pourront être approfondies ultérieurement et sur demande.

  • 239