sequenceDiagram
Workspace ->> Staging index: add
Staging index ->> Local repository: commit
Local repository ->> Remote repository: push
Remote repository ->> Workspace: pull
Introduction Ă Git
Introduction
- Outil indispensable
- Utilisation :
- TP informatiques, R
- Dans tous vos projets
- Dans votre vie professionnelle
- Utilisé en projet
- ĂvaluĂ© en ComplĂ©ments dâinfo 2A
- Suivi dâun TP
â ïž valable pour tous les TP :
- lisez le sujet avant
- soyez prĂȘts (pas 20 min pour se logger)
- nâallez pas trop vite
- suivez précisément les consignes
- réfléchissez (il peut y avoir des coquilles)
- < ⊠> -> remplacer
Introduction
Vous faites partie dâune Ă©quipe de 5 personnes qui doit coder une application de jeux de cartes.
đ Comment mettre en commun votre code ?
- Vous développez chacun de votre cÎté et à la fin, vous mettez tout en commun
- Vous envoyez vos programmes par mail
- Vous créez un dossier commun
đ En cas dâerreur, comment revenir en arriĂšre ?
On va essayer de trouver un moyen pour bosser efficacement.
Au programme
- đ Versionner son code
- đŸ Historique des modifications
- đ· Travail en Ă©quipe
2 grandes problématiques :
- Versionner le code
- Partager du code
Pourquoi versionner ?
- Quelle est la bonne version ?
- Comment faire pour revenir en arriĂšre ?
- Qui a écrit ce code ? Quand ?
- les questions que lâon peut se poser en projet
- Mais qui a écrit cette merde ???
- ah ben câest moi⊠il y a 2 ans
- plutĂŽt bon signe -> ça veut dire quâon progresse
Pour connaßtre la véritable derniÚre version
MĂȘme si vous ĂȘtes bien intentionnĂ©, ça finira par dĂ©raper
Solutions naĂŻves :
- Pas de versionnage
- vous écrasez les anciens fichiers
- Copier intégralement le dossier à chaque modif
- projet_v1, projet_v2
- incrémenter les noms de fichier
ââââ Projet info
â ââââ old
â â ââââ Rapport.qmd
â â ââââ Rapport_new.qmd
â â ââââ Rapport_v1.0.qmd
â â ââââ Rapport_v1.0_new_old.qmd
â â ââââ Rapport_v1.1.qmd
â ââââ Rapport_old.qmd
â ââââ Rapport_2022.05.15.qmd
â ââââ Rapport_2022.05.15_latest.qmd
đ Quelle est la bonne version du fichier ?
đ Un seul fichier + lâhistorique des modifications
ââââProjet info
â ââââLivrables
â ââââRapport.qmd
Date Heure Auteur Message commit
---- ----- ------ --------------
2022.05.29 23h58 bianca "Version finale"
2022.05.29 23h40 archibald "j'avais oublié l'intro"
2022.05.29 21h32 tryphon "ajout partie 2"
2022.05.29 20h25 bianca "v1.1"
2022.05.29 20h12 tryphon "Création du rapport"
Ancien code commenté
Vous souhaitez passer de R-base Ă ggplot2 pour votre graphique.
Mais vous vous dites que câest mieux de garder lâancien code au cas oĂčâŠ
analyse.R
library(ggplot2)
data <- data.frame(x = seq(-4, 4, length=100))
data$y <- dnorm(data$x)
# plot(data$x, data$y, type="l", lwd=2, col="blue",
# main="Densité de la loi normale centrée réduite",
# xlab="x", ylab="Densité")
# abline(h=0, col="gray")
ggplot(data, aes(x = x, y = y)) +
geom_line(color = "blue", size = 1) +
ggtitle("Densité de la loi normale centrée réduite") +
xlab("x") +
ylab("Densité") +
theme_minimal()analyse.R - Commit 05016ab - Date 2024.06.02 - Author tryphon
data$y <- dnorm(data$x)
plot(data$x, data$y, type="l", lwd=2, col="blue",
main="Densité de la loi normale centrée réduite",
xlab="x", ylab="Densité")
abline(h=0, col="gray")analyse.R - Commit f97f766 - Date 2024.06.04 - Author bianca
library(ggplot2)
data <- data.frame(x = seq(-4, 4, length=100))
data$y <- dnorm(data$x)
ggplot(data, aes(x = x, y = y)) +
geom_line(color = "blue", size = 1) +
ggtitle("Densité de la loi normale centrée réduite") +
xlab("x") +
ylab("Densité") +
theme_minimal()Git
- git : connard en argot britannique
Objectifs :
- 1A apprentissage
- 2A fluent
- 3A maitrise
Historique
- Créé par Linus Torvalds en 2005
- Pour gérer le développement du noyau Linux
- Le standard incontournable de la gestion de versions
- Anciens outils : CVS, SVN
- Standard : produit qui sâest imposĂ© par lâusage (ex : Moteur de recherche Google, TCP/IP)
- peu causer des problĂšmes de monopoleâŠ
Logiciel
- Logiciel Libre, Open source
- Gratuit
- Décentralisé
đš Git sâutilise majoritairement en ligne de commande dans un terminal Git Bash.
đ
Pas de panique, quelques commandes suffisent pour travailler avec Git.
Il existe aussi des interfaces graphiques mais elles sont souvent imparfaites et sources dâerreur.
- Logiciel libre
- code source est ouvert et disponible
- permettant Ă quiconque de lâutiliser, le modifier, et le distribuer librement
- différent de gratuit
- légÚrement différent de Open source
- Open Source : avantages pratiques et collaboratifs
- Libre : libertés et les droits éthiques des utilisateurs
- Décentralisé
- chaque utilisateur dispose dâune copie complĂšte de lâhistorique de tout le projet
Késako
- Git âĄïž Logiciel de gestion de versions
- Git Bash âĄïž Terminal pour Ă©crire des commandes git
- GitHub / GitLab âĄïž Plateforme de dĂ©veloppement collaboratif
- Héberge des dépÎts Git
- Propose dâautres fonctionnalitĂ©s (CI/CD, wiki, gestion des incidentsâŠ)
- GitHub racheté par Microsoft en 2018
- GitLab, Libre, possible dâavoir son propre GitLab interne
Git Bash
- Terminal de commande
- Plusieurs maniĂšres de lancer (Menu Windows, clic droit, inclus dans VSCode)
Conseil : lors de lâinstallation de Git, choisissez le terminal Unix
- 1ere ligne : prompt (username, machine, répertoire actuel)
- 2e ligne (commence par $) : commande
- 3e ligne : résultat de la commande
Bref aparté sur les commandes Unix.
Il fut un temps oĂč tout se faisait par ce biais (pas dâexplorer)
Commandes Unix
| Commande | Description |
|---|---|
ls (ou ll) |
Liste le contenu dâun rĂ©pertoire |
pwd |
Affiche le répertoire courant |
cd <directory> |
Change le répertoire de travail courant |
mv <src_file> <dest_file> |
Déplace des fichiers ou des répertoires |
cp <src_file> <dest_file> |
Copie un fichier ou un répertoire |
mkdir <directory> |
Crée un nouveau répertoire |
rm <file_or_dir> |
Supprime des fichiers ou des répertoires |
touch <filename> |
Crée un nouveau fichier vide |
cat <filename> |
Affiche le contenu dâun fichier |
grep <text> <filename> |
Rechercher dans un fichier |
| Commande | Signification |
|---|---|
ls (ou ll) |
list |
pwd |
print working directory |
cd <directory> |
change directory |
mv <src_file> <dest_file> |
move |
cp <src_file> <dest_file> |
copy |
mkdir <directory> |
make directory |
rm <file_or_dir> |
remove |
touch <filename> |
|
cat <filename> |
concatenate |
grep <text> <filename> |
global regular expression print |
- ce qui est entre < ⊠> est à remplacer
- ll : ls -l
- cd : change directory
- pwd : print working directory
- mkdir : make directory
- pour éditer un fichier : vi, nano
- man
Attention avec les commandes rm, kill
Commandes Unix - Exemples
Pour chaque commande, de nombreuses options sont disponibles
ls *.py # liste tous les fichiers python du répertoire courant
ls *.py > a.txt # crée un fichier a.txt contenant le résultat de la commande
cd .. # se positionne dans le répertoire parent
cd ../projet/src # remonter dans le dossier parent puis aller dans projet puis src
cp /p/image.jpg . # copie le fichier image.jpg du disque P dans le dossier courant
./setup.sh # lance le programme setup.sh du rĂ©pertoire courant.: reprĂ©sente le dossier courant..: reprĂ©sente le dossier parent~: rĂ©pertoire personnel de lâutilisateur (echo $HOME)
répertoire = dossier
La ligne de commande reste trÚs utilisée :
- rapide, efficace
- automatisation
- exemple : renommer 1000 fichiers dâun dossier
git add .: add current
Copier-Coller
- CTRL + C et CTRL + V ne fonctionnent pas toujours !
- CTRL + C : stopper un processus (trĂšs utile)
2 possibilités pour coller du texte :
- Clic droit
- MAJ + INSERT
Raccourcis indispensables:
- CTRL+ A : select all
- TABULATION: autocomplete
- HISTORIQUE âŹïž et âŹïž
Versionner son code
- Au dĂ©but jâai parlĂ© de versionner
- Comment faire avec Git
Que versionne-t-on ?
- â des fichiers de type texte (lĂ©gers)
- â du code source
- â fichiers de donnĂ©es
- â mots de passe
- â outputs : logs, .pdf, .doc
- un dépÎt doit rester léger
- quelques Mo max
- possible de mettre du doc ou pdf
- mais git ne sait comparer que du txt, csv, md
- tout ce qui peut sâouvrir avec notepad
Workflow
Retenir Local et Remote, mais en fait câest un peu plus complexe :
- ça fait un peu peur, pas intuitif au début
- workspace : tous les fichiers de votre dossier
- staging : fichiers reconnus par git
- local : sauvegardes du dépÎt local
Plus facile dans un sens que lâautre
Créer un commit
2 étapes pour créer une nouvelle version :
git add <filename>- ajouter le fichier Ă lâindex (i.e. dire Ă Git de suivre ce fichier)
git add .: pour ajouter tous les fichiers
git commit -m "<mon message>"
- git utilise la sauvegarde incrémentale
- il ne garde que les modifs apportées depuis le dernier commit
https://talks.freelancerepublik.com/git-commandes-indispensables-developpeurs/
Exemple
ââââ Projet info
â ââââ src
â â ââââ main.py
â ââââ doc
â â ââââ Rapport.txtVotre dĂ©pĂŽt avant de commencer Ă coder.
ââââ Projet info
â ââââ src
â â ââââ main.py <- fichier modifiĂ©
â â ââââ velo.py <- nouveau fichier
â ââââ doc
â â ââââ Rapport.txtVous avez :
- modifié un fichier
- créé un nouveau fichier
Vous ajoutez les fichiers créés ou modifiĂ©s Ă lâindex :
git add .
Vous créez un point de sauvegarde
git commit -m "feat: ajout de l'utilisation de velo"
git checkout <commit_number> : les fichiers de votre dĂ©pĂŽt sont alors dans lâĂ©tat oĂč ils Ă©taient Ă ce commit
Message du commit
đ Ce nâest pas toujours Ă©vident de trouver un message court et explicite.
Utilisez un préfixe à votre message selon le pattern <type>: <sujet>:
doc:mise à jour documentairefeat:nouvelle fonctionnalitéfix:correctionrefactor:mise au propre du coderevert:retour arriÚretest:Modification des tests
Suffixe WIP
Mon petit commit
Privilégiez de nombreux petits commits à un gros commit final :
- Un commit = une modification cohérente
- Plus facile de comprendre lâhistorique
- Plus facile de revenir en arriĂšre
Retour arriĂšre
Si finalement, vous nâavez pas envie de « commiter » vos modifications ?
| Commande | Description |
|---|---|
git restore <file> |
Annuler les modifications locales non indexées du fichier |
git reset <file> |
Desindexer un fichier |
git reset --hard |
Revenir Ă lâĂ©tat du dernier commit, perdant toutes les modifications locales |
git stash |
Sauvegarder et remettre le working directory Ă lâĂ©tat du dernier commit |
Attention avec les commandes contenant les mots force, hardâŠ
Ignorer des fichiers
.gitignore est un fichier prĂ©sent Ă la racine du dĂ©pĂŽt permettant de dire Ă Git quels fichiers il doit ignorer. Par exemple, sâil contient :
*.csvâĄïž tous les fichiers csv seront ignorĂ©s par Gitdata/âĄïž le dossier data et son contenu sera ignorĂ©
Cela est utile, pour exclure par exemple du dépÎt Git :
- des fichiers contenant des mots de passe, des jetons dâaccĂšsâŠ
- des fichiers volumineux de donnĂ©es qui nâont pas vocation Ă ĂȘtre versionnĂ©s
- des fichiers de log
- En info, il y a souvent plein de fichiers de config
- â ïž Mots de passe âĄïž git garde tout lâhistorique
- Next
- câĂ©tait pour la partie âgestion du dĂ©pĂŽt localâ
- ensuite regardons comment communiquer avec le dépÎt distant
Exemple
.gitignore
.env
.venv/
__pycache__/
.pytest_cache/
.ruff_cache/
*.log
doc/exams/**/*2026*Git / pas Git ?
Un petit quizz !
Projet info
Projet info/
âââ .github/
â âââ workflows/
â âââ ci.yml
âââ backend/
â âââ pyproject.toml
â âââ src/
â âââ dao/
â âââ service/
â âââ main.py
âââ data/
â âââ create_tables.sql
â âââ insert_data.sql
âââ doc/
â âââ rapport.qmd
â âââ suivi.md
âââ .env
âââ .gitignore
âââ docker-compose.yml
âââ README.md
Git mais attention :
- dossier data/ -> bof
- fichier .env -> mots de passeâŠ
Projet éco
Les Nudges/
âââ Articles/
â âââ Sunstein_2014_Nudging.pdf
â âââ Kahneman_1990.pdf
â âââ Nudges that dont nudge.pdf
âââ Notes/
â âââ idees.docx
â âââ bibliographie.docx
â âââ donnĂ©es.csv
âââ Rapport/
âââ rapport.docx
âââ rapport_v2.docx
âââ rapport_v3_final.docx
âââ rapport_v3_final.pdf
âââ rapport_v3_final_corrige.docx
âââ presentation.pptx
âââ presentation_finale.pptx
Pas Git :
- versions gérées manuellement
- beaucoup de fichiers Word/PDF
Projet stat
Projet Loto/
âââ .gitignore
âââ README.md
âââ suivi.md
âââ data/
â âââ README.md
â âââ loto.csv
âââ R/
â âââ 01_load.R
â âââ 02_clean.R
â âââ 03_explore.R
â âââ 04_analyze.R
â âââ 05_visualize.R
âââ rapport/
â âââ rapport.qmd
â âââ rapport.pdf
âââ presentation/
âââ soutenance.qmd
Git :
- fichiers versionnés
- Repo bien organisé
Réglement de scolarité
Jâai pris un exemple dans une Ă©cole au hasard, câest pas chez nous
Travailler en équipe
DépÎt local et dépÎt distant
- 1 dépÎt distant
- appelé aussi remote
- hĂ©bergĂ© sur une forge (GitHub, GitLabâŠ)
- n dépÎts locaux
- clone sur votre machine
- git permet la synchronisation des dépÎts
Il est tout Ă fait possible dâavoir plusieurs clones du mĂȘme dĂ©pĂŽt sur son poste.
- avoir un accÚs internet / réseau local pour communiquer avec remote
- câĂ©tait pas nĂ©cessaire pour faire des add / commit
Commencer dessin avec :
- un remote v0
- 2 clones de Bob et Alice en v0
DépÎt local et dépÎt distant
Chaque dépÎt est une copie intégrale du projet.
flowchart
github[(DépÎt distant)]
dev1[(DépÎt local 1)]
dev2[(DépÎt local 2)]
github <--> dev1
github <--> dev2
Comme une cellule du corps humain.
- Si vous perdez un dĂ©pĂŽt, il suffit de repartir dâun autre
Communiquer avec le dépÎt distant
git pull: mettre à jour son dépÎt local à partir du dépÎt distantgit push: envoyer ses commits locaux sur le dépÎt distant
Il est important de push et pull réguliÚrement son code pour garder son dépÎt à jour.
Vous faites toujours vos actions sur un dépÎt local.
Vous ne modifiez jamais le dépÎt distant.
- push and pull réguliers sinon vos versions vont diverger
git push
DĂ©pĂŽt local âĄïž DĂ©pĂŽt distant
Pour pouvoir pousser son code, il est nécessaire :
- dâavoir au prĂ©alable créé au minimum un commit
- que votre dépÎt local soit à jour
- pas de retard de version par rapport au dépÎt distant
- si ce nâest pas le cas, il faut commencer par
git pull
Vous pouvez push plusieurs commits
git push - si votre dĂ©pĂŽt local nâest pas Ă jour
! [rejected] main -> main (fetch first)
error: failed to push some refs
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Le message est assez explicite.
git push - fichier disparu
- Vous venez de faire un
git push - Mais votre fichier nâapparait pas sur le dĂ©pĂŽt distantâŠ
- Probablement parce que vous avez oubliĂ© de lâajouter Ă lâindex avec
git add <mon_fichier>
Autre possibilité : votre fichier est ignoré par git car il fait partie du .gitignore
ça arrive quand vous voulez aller trop vite
git pull
DĂ©pĂŽt local âŹ ïž DĂ©pĂŽt distant
- Mise à jour de votre dépÎt local
- Sâil y a eu des modifications sur le dĂ©pĂŽt distant
Un pull se fait généralement aprÚs un commit.
git pull - conflit
Que se passe-t-il si :
- Alice a modifié un fichier et poussé sa modification sur le dépÎt distant
- Vous avez Ă©galement modifiĂ© le mĂȘme fichier et vous faites un
git pullpour mettre à jour votre dépÎt à partir du dépÎt distant
đš Un conflit ! Git ne sait pas choisir quelle est la bonne version entre la vĂŽtre et celle dâAlice.
git pull - conflit
đ Pas de panique ! Pour rĂ©soudre le conflit, il faut simplement :
- modifier le fichier en question pour garder la bonne version
git addpuisgit commitpour valider la résolution du conflit
Il apparaßt sur votre dépÎt local.
- conflit â erreur
- ça arrive
2 versions sâopposent
- câest un exemple, il peut y avoir dâautres types
- git est assez bon pour merge (mĂȘme si 2 modifs sur mĂȘme fichier)
- mais en cas de doute, il ne peut pas choisir
velo.py
class Velo:
def __init__(self, couleur):
self.couleur = "bleu"velo.py
class Velo:
def __init__(self, couleur):
self.couleur = "blanc"velo.py
class Velo:
def __init__(self, couleur):
self.couleur = "noir"Résoudre un conflit
- Contexte
- Premier arrivé, premier servi
- Le conflit (aprĂšs votre pull)
- Conflit
- Git nâest pas un juge
- VSCode : accept incoming/current/both change
- Résolution
- supprimez les
<<<<<<<et=======âĄïž pas du python - si vous relancez votre programme comme ça, il va pas aimer
- supprimez les
Le conflit se résout sur son dépÎt local !
- Alice a poussé son code avant vous
- Vous faites donc un
git pull- En effet, vous devez impérativement mettre à jour votre dépÎt local avant de pousser votre code
- 2 versions sâopposent sur votre dĂ©pĂŽt local
self.couleur = "noir"vsself.couleur = "blanc"
- Git nâest pas capable de choisir laquelle est la bonne đ€·ââ
- En haut : votre version
- En bas : celle provenant du dépÎt distant
class Velo:
<<<<<<< HEAD
def __init__(self, nom, couleur, vitesse_max):
self.couleur = "noir"
=======
def __init__(self, nom, couleur, marque):
self.couleur = "blanc"
>>>>>>> a57ae9120dbf97dbab78f82db81f5fc8f48f3821Pour résoudre ce conflit, 3 possibilités :
- vous choisissez votre code
- vous choisissez celui dâAlice
- vous choisissez un mix des 2
Ensuite, vous validez, créez un commit et poussez le code (git add ., puis git commit -m "<message>" et git push).
Etat du dépÎt local
Est-ce quâil y a des fichiers :
- non suivis ? Untracked files
- prĂȘts Ă ĂȘtre commitĂ©s ? Changes to be committed
- modifiĂ©s non ajoutĂ©s Ă lâindex ? Changes not staged for commit
La commande git status permet de répondre à ces questions.
Elle peut ĂȘtre utilisĂ©e nâimporte quand, sans modĂ©ration ! đ»
git status
Est-ce que votre dépÎt local est en avance de n commit par rapport au dépÎt distant ?
Cloner un dépÎt
Pour créer votre dépÎt local.
git clone
- Allez sur la page du dĂ©pĂŽt distant (GitHub, GitLabâŠ)
- Cliquez sur le bouton
Code - Copiez lâadresse https ou ssh du dĂ©pĂŽt distant
git clone <adresse_depot>- exemples :
git clone https://github.com/ludo2ne/Git-tuto.git(https)git clone git@github.com:ludo2ne/Git-tuto.git(ssh)
Créer sans cloner
Il est possible de créer un dépÎt local sans cloner un dépÎt distant (git init).
Et éventuellement ensuite de le brancher à un dépÎt distant.
Cependant ce cas dâutilisation est assez marginal.
https ou ssh ?
2 protocoles différents pour communiquer avec le dépÎt distant.
Ă utiliser sur les datalabs.
- Plus simple, pas besoin de configuration
- Nécessite un token si vous voulez pousser du code
Ă utiliser si vous travaillez sur la VM ENSAI.
- Configuration initiale des clés SSH
- Plus pratique pour des interactions fréquentes
- Pas de saisie de mot de passe aprĂšs configuration
- ssh :
- clé publique / clé privée -> config machine
- vous générez un secret depuis votre machine
- https :
- GitHub génÚre un token
Commandes principales
| Commande | Description |
|---|---|
git clone <adr> |
Créer un dépÎt local sur son poste |
git status |
Voir oĂč lâon en est |
git add <file> |
Ajouter pour le prochain commit |
git commit -m "<msg>" |
Créer un point de sauvegarde |
git pull |
dĂ©pĂŽt local âŹ ïž dĂ©pĂŽt distant |
git push |
dĂ©pĂŽt local âĄïž dĂ©pĂŽt distant |
clone : bouton vert code sur GitHub, GitLab
Autres commandes
git diff: différence avec le dernier commitgit diff <filename>
git checkout <commit_number>: passer à un commit spécifiquegit log: historique des commitsgit log --all --decorate --oneline --graph
La routine Git
- pull : des fois quâun camarade ait codĂ© la nuit
Travailler sur le Datalab
- Services non pérennes
- Sauvegarder votre code
âȘ Indispensable dâutiliser Git !
- vous ne travaillerez pas toujours en local
- mais parfois sur des services Ă la demande
- ex : besoin de puissance de calcul
Aller plus loin
- Les branches
- GitFlow
- Pull request
- Open source
Glossaire
Les bases
| Terme | Synonymes | Signification |
|---|---|---|
| Git | Outil de versionnage | Logiciel qui gĂšre les versions et lâhistorique du code |
| GitHub | Plateforme Git | Service web pour héberger et collaborer sur des dépÎts Git |
| Git Bash | Terminal | Terminal pour lancer des commandes Git |
| DépÎt | Repository, Repo | Dossier contenant un projet Git (code + historique) |
| Remote | DĂ©pĂŽt distant | DĂ©pĂŽt hĂ©bergĂ© sur un serveur (GitHub, GitLabâŠ) |
| Local | DĂ©pĂŽt local, Clone | Copie dâun Remote sur ordinateur, ou dans ton service |
| Commit | Point de sauvegarde | Ătat du projet Ă un instant donnĂ© |
| Push | Envoyer | Transmettre les commits locaux vers le dépÎt remote |
| Pull | Récupérer | Ramener les commits du remote vers le local et les fusionner |
Autres
| Terme | Synonymes | Signification |
|---|---|---|
| Branche | Branch | Ligne parallÚle de développement dans un dépÎt |
| Main | Master | Branche principale (tronc) |
| Merge | Fusion | Action de combiner une branche dans une autre |
| Fork | Copier un remote | Copier un remote sur son propre compte GitHub |
| Issue | Ticket | Outil pour signaler un bug, une tĂąche ou une discussion |
| Pull Request | PR, Merge Request | Proposition dâintĂ©grer des changements dâune branche vers une autre |
Bibliographie
- Git : un élément essentiel au quotidien, Python pour la datascience, Lino Galiana
- Formation Git du Lab INSEE
- Formation Git du SSM Agriculture
- GitFlow
- Développement basé sur le tronc


