Imaginez une situation sans Git : vous travaillez sur un projet en équipe.
Projet/ ├── MonApplication.java ├── MonApplication_v2.java ├── MonApplication_v2_final.java ├── MonApplication_v2_final_ALICE.java ├── MonApplication_v2_final_ALICE_corrigé.java └── MonApplication_UTILISER_CELUI_LA.java ← Lequel ???
Les problèmes sans versioning : Qui a fait quoi ? Quand ? Pourquoi ? Comment revenir à une version qui fonctionnait ? Comment plusieurs personnes travaillent sur le même fichier en même temps ? Comment savoir quelle version est en production ?
Les problèmes sans versioning :
Git est un système de contrôle de version distribué (DVCS — Distributed Version Control System) créé par Linus Torvalds en 2005 (le créateur de Linux).
Analogie : Git est comme un historique de sauvegarde ultra-puissant pour votre code. Imaginez un document Word où chaque modification est enregistrée avec la date, l’auteur, et la raison du changement — et où vous pouvez revenir à n’importe quel état passé en un clic.
Ce que Git permet :
C’est une source de confusion fréquente :
Analogie : Git est comme le protocole email (SMTP). GitHub/GitLab sont comme Gmail ou Outlook — des interfaces qui utilisent ce protocole.
Dans ce cours, nous utilisons GitLab car :
Avant de taper la moindre commande, il faut comprendre le vocabulaire et les mécanismes de Git.
Un dépôt (ou repo) est le dossier de votre projet qui contient à la fois vos fichiers et tout l’historique des modifications. Git stocke cet historique dans un sous-dossier caché .git/.
.git/
mon-projet/ ├── .git/ ← Le "cerveau" de Git — ne jamais modifier manuellement ! │ ├── HEAD │ ├── objects/ │ └── refs/ ├── src/ │ └── Main.java └── README.md
Il existe deux types de dépôts :
C’est le concept le plus important à comprendre. Chaque fichier peut se trouver dans une de ces trois zones :
┌─────────────────┐ git add ┌─────────────────┐ git commit ┌─────────────────┐ │ │ ──────────→ │ │ ────────────→ │ │ │ WORKING DIR │ │ STAGING AREA │ │ REPOSITORY │ │ (Répertoire │ │ (Zone de │ │ (Historique │ │ de travail) │ ←────────── │ transit / │ │ des commits) │ │ │ git restore │ Index) │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ Vos fichiers Prêts à être Sauvegardés modifiés validés définitivement
Working Directory (Répertoire de travail) : C’est simplement votre dossier de travail — les fichiers tels que vous les voyez dans votre explorateur. Quand vous modifiez un fichier, la modification reste ici jusqu’à ce que vous la “stagiez”.
Staging Area (Zone de transit / Index) : C’est une zone intermédiaire où vous préparez votre prochain commit. Vous choisissez précisément quelles modifications vous souhaitez inclure dans le prochain enregistrement. C’est comme préparer un colis avant de l’envoyer.
Repository (Dépôt local) : L’historique permanent de tous vos commits. Une fois qu’un commit est fait, il est conservé indéfiniment (sauf action explicite).
Exemple concret : Vous modifiez 5 fichiers en une matinée. Vous voulez créer deux commits distincts : un pour la nouvelle fonctionnalité (3 fichiers), un pour la correction de bug (2 fichiers). La staging area vous permet de sélectionner précisément les fichiers de chaque commit.
Un commit est un enregistrement d’un état du projet à un instant donné. C’est l’unité de base de Git.
Chaque commit contient :
a3f2b1c9...
commit a3f2b1c9d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9 Author: Alice Dupont <alice@example.com> Date: Mon Jan 15 09:30:00 2024 +0100 feat: ajouter la fonctionnalité de recherche par auteur - Ajout de la méthode findByAuthor() dans BookRepository - Ajout du endpoint GET /api/books/search?author=... - Tests unitaires correspondants
La chaîne de commits : Les commits forment une chaîne chronologique. Chaque commit pointe vers son parent, créant ainsi l’historique du projet.
[commit 1] → [commit 2] → [commit 3] → [commit 4] ← HEAD (position actuelle) "init" "feat:..." "fix:..." "feat:..."
HEAD est un pointeur qui indique votre position actuelle dans l’historique. En temps normal, HEAD pointe vers le dernier commit de la branche active.
main → [C1] → [C2] → [C3] → [C4] ↑ HEAD
Une branche est une ligne de développement indépendante. C’est techniquement juste un pointeur vers un commit.
main : [C1] → [C2] → [C3] → [C4] ↓ feature : [C3] → [C5] → [C6]
Analogie : Imaginez un arbre. Le tronc est la branche principale (main). Les branches latérales sont les fonctionnalités en cours de développement. Elles peuvent se développer indépendamment, puis être “greffées” (fusionnées) sur le tronc.
main
Windows :
Téléchargez Git for Windows sur https://git-scm.com/download/win L’installateur inclut Git Bash (un terminal Unix pour Windows).
macOS :
# Avec Homebrew brew install git # Ou via Xcode Command Line Tools xcode-select --install
Linux (Ubuntu/Debian) :
sudo apt update sudo apt install git
Vérifier l’installation :
git --version # git version 2.43.0
Avant toute chose, configurez votre identité. Ces informations apparaîtront dans chaque commit que vous créez.
# Votre nom (tel qu'il apparaîtra dans les commits) git config --global user.name "Alice Dupont" # Votre email (doit correspondre à votre compte GitLab) git config --global user.email "alice.dupont@example.com" # Éditeur de texte par défaut (pour les messages de commit) git config --global core.editor "nano" # ou "vim", "code" pour VS Code # Définir 'main' comme nom de branche principale par défaut git config --global init.defaultBranch main # Activer les couleurs dans le terminal git config --global color.ui auto # Stratégie de pull (recommandée) git config --global pull.rebase false
Vérifier la configuration :
git config --list # Affiche toute la configuration git config user.name # Alice Dupont
Portées de la configuration :
--global # S'applique à tous vos projets (stocké dans ~/.gitconfig) --local # S'applique uniquement au dépôt courant (stocké dans .git/config) --system # S'applique à tous les utilisateurs de la machine
Pour communiquer avec GitLab sans saisir son mot de passe à chaque fois, utilisez SSH.
# 1. Générer une clé SSH ssh-keygen -t ed25519 -C "alice.dupont@example.com" # Appuyez sur Entrée pour les questions (emplacement et passphrase optionnelle) # 2. Afficher la clé publique cat ~/.ssh/id_ed25519.pub # Copiez tout le contenu affiché # 3. Ajouter dans GitLab : # → Profil GitLab → Préférences → Clés SSH → Coller la clé → Ajouter # 4. Tester la connexion ssh -T git@gitlab.com # Welcome to GitLab, @alice_dupont!
# Créer un nouveau dépôt Git dans le dossier courant git init # Ce que ça fait : # Crée un dossier .git/ dans le répertoire courant # Le dépôt est vide — aucun commit encore # Vérifier que Git est initialisé ls -la # On voit le dossier .git/
# Cloner depuis GitLab (SSH — recommandé) git clone git@gitlab.com:mon-groupe/mon-projet.git # Cloner depuis GitLab (HTTPS) git clone https://gitlab.com/mon-groupe/mon-projet.git # Cloner dans un dossier avec un nom spécifique git clone git@gitlab.com:mon-groupe/mon-projet.git mon-dossier # Ce que ça fait : # Crée un dossier avec tous les fichiers du projet # Configure automatiquement le remote "origin" # Récupère tout l'historique
git status
Exemple de sortie :
On branch main Your branch is up to date with 'origin/main'. Changes to be committed: ← Dans la staging area (use "git restore --staged <file>..." to unstage) new file: src/Main.java Changes not staged for commit: ← Modifiés mais pas stagés (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: README.md Untracked files: ← Nouveaux fichiers, pas encore trackés (use "git add <file>..." to include in what will be committed) config.properties
Interprétation des couleurs : Rouge : modifications non stagées (dans le working dir) Vert : modifications stagées (dans la staging area, prêtes pour le commit)
Interprétation des couleurs :
# Ajouter un fichier spécifique git add src/Main.java # Ajouter plusieurs fichiers git add src/Main.java src/Utils.java # Ajouter tous les fichiers modifiés et nouveaux git add . # Ajouter tous les fichiers d'un dossier git add src/ # Ajouter de manière interactive (choisir les parties à stager) git add -p # Très utile pour séparer les modifications en plusieurs commits
git add . ajoute TOUT — y compris des fichiers que vous ne voulez pas versionner (comme des fichiers de configuration locale, des secrets, des dossiers target/). C’est pour ça qu’on utilise .gitignore.
git add .
target/
.gitignore
.gitignore liste les fichiers et dossiers que Git doit ignorer complètement.
# .gitignore pour un projet Java/Spring Boot # ← Les commentaires commencent par # # Dossier de compilation Maven/Gradle target/ build/ *.class # Fichiers d'IDE .idea/ *.iml .eclipse/ .settings/ .classpath .project # Fichiers de log *.log logs/ # Fichiers de configuration sensibles (JAMAIS dans Git !) application-prod.properties *.env .env # Fichiers système .DS_Store # macOS Thumbs.db # Windows desktop.ini # Dossier node_modules (si frontend) node_modules/ # Patterns avancés *.tmp # Tous les fichiers .tmp !important.tmp # Sauf important.tmp (! = exception) doc/**/*.pdf # Tous les PDF dans n'importe quel sous-dossier de doc/
Conseil : Générez votre .gitignore sur https://gitignore.io en saisissant votre stack technique (Java, Maven, IntelliJ, etc.).
# Créer un commit avec un message git commit -m "feat: ajouter la page de connexion utilisateur" # Ouvrir l'éditeur pour un message multiligne git commit # Une fois dans l'éditeur, écrivez votre message et sauvegardez # Raccourci : stager ET committer tous les fichiers déjà trackés git commit -am "fix: corriger le bug d'affichage du menu" # ATTENTION : ne stager PAS les nouveaux fichiers (untracked) # Modifier le dernier commit (avant push !) git commit --amend -m "feat: ajouter la page de connexion avec validation"
Un bon message de commit répond à la question : “Que fait ce commit si on l’applique ?”
Format recommandé (Conventional Commits) :
type(scope): description courte en minuscules Corps optionnel : explication détaillée si nécessaire. On peut mettre plusieurs lignes. Footer optionnel : référence aux tickets/issues Closes #123
Types de commits :
feat
fix
docs
style
refactor
test
chore
perf
ci
Exemples de bons messages :
feat(auth): ajouter la connexion via Google OAuth fix(panier): corriger le calcul des remises cumulées docs(readme): mettre à jour les instructions d'installation test(user-service): ajouter les tests d'intégration de UserService chore(deps): mettre à jour Spring Boot vers 3.2.0
Exemples de mauvais messages :
✗ "fix" ← Trop vague ✗ "modifications" ← Inutile ✗ "ça marche maintenant" ← Aucune info ✗ "WIP" ← Work In Progress = pas fini ✗ "asdfgh" ← Test ou fatigue ✗ "Correction du bug #2 de la feature ajoutée hier après-midi par Bob quand il a..." ← Trop long
Règle d’or : La description courte fait 50 caractères maximum, commence par une minuscule, et n’a pas de point final. Le corps du commit est séparé par une ligne vide et fait 72 caractères par ligne max.
# Historique complet git log # Historique compact (une ligne par commit) git log --oneline # a3f2b1c feat: ajouter la recherche par auteur # 7d8e9f0 fix: corriger la validation du formulaire # 1a2b3c4 feat: créer la page d'accueil # Historique avec graphe des branches git log --oneline --graph --all # * a3f2b1c (HEAD -> main) feat: ajouter la recherche # * 7d8e9f0 fix: corriger la validation # | * 5e6f7a8 (feature/panier) feat: ajouter le panier # |/ # * 1a2b3c4 feat: créer la page d'accueil # Voir les modifications d'un commit spécifique git show a3f2b1c # Historique d'un fichier spécifique git log --follow src/Main.java # Rechercher dans les messages de commit git log --grep="panier" # Commits par auteur git log --author="Alice" # Commits entre deux dates git log --after="2024-01-01" --before="2024-02-01"
# Différences dans le working directory (non stagées) git diff # Différences dans la staging area (stagées, prêtes pour commit) git diff --staged # ou : git diff --cached # Différences entre deux commits git diff a3f2b1c 7d8e9f0 # Différences entre deux branches git diff main feature/panier # Différences d'un fichier spécifique git diff src/Main.java
Lecture d’un diff :
diff --git a/src/Main.java b/src/Main.java index 1234567..abcdefg 100644 --- a/src/Main.java ← Version avant +++ b/src/Main.java ← Version après @@ -10,6 +10,8 @@ ← Lignes concernées public class Main { - private String name; ← Ligne supprimée (rouge) + private String firstName; ← Ligne ajoutée (verte) + private String lastName; ← Ligne ajoutée (verte) public void run() {
# Annuler les modifications dans le working dir (avant git add) git restore src/Main.java # IRRÉVERSIBLE : les modifications sont perdues définitivement # Déstaguer un fichier (après git add, avant git commit) git restore --staged src/Main.java # Les modifications restent dans le working dir # Créer un commit qui annule un commit passé (SÛRE) git revert a3f2b1c # Crée un nouveau commit qui inverse les changements de a3f2b1c # L'historique est préservé — recommandé pour les branches partagées # Revenir en arrière dans l'historique (DANGEREUSE) git reset --soft HEAD~1 # Annule le dernier commit, garde les modifs stagées git reset --mixed HEAD~1 # Annule le dernier commit, garde les modifs (non stagées) git reset --hard HEAD~1 # Annule le dernier commit ET les modifications — IRRÉVERSIBLE ! # Règle d'or : N'utilisez JAMAIS git reset sur des commits déjà poussés (push)
** Résumé des actions d’annulation :** Situation Commande Modifier un fichier → annuler avant git add git restore <fichier> Après git add → déstaguer git restore --staged <fichier> Après git commit → annuler proprement git revert <hash> Dernier commit local pas encore pushé git reset --soft HEAD~1
** Résumé des actions d’annulation :**
git add
git restore <fichier>
git restore --staged <fichier>
git commit
git revert <hash>
git reset --soft HEAD~1
Vous êtes en train de travailler sur une fonctionnalité quand on vous demande de corriger un bug urgent. Vous ne voulez pas committer un travail inachevé. git stash met vos modifications de côté temporairement.
git stash
# Mettre les modifications de côté git stash # ou avec un nom git stash push -m "travail en cours sur le panier" # Voir les stash enregistrés git stash list # stash@{0}: On feature/panier: travail en cours sur le panier # stash@{1}: On main: modifs temporaires # Récupérer le dernier stash (et le supprimer de la liste) git stash pop # Récupérer un stash spécifique git stash apply stash@{1} # Supprimer un stash git stash drop stash@{0} # Supprimer tous les stash git stash clear
# Voir toutes les branches locales git branch # * main ← L'étoile indique la branche courante # feature/panier # fix/bug-login # Voir toutes les branches (locales + distantes) git branch -a # * main # feature/panier # remotes/origin/main # remotes/origin/develop # Créer une nouvelle branche git branch feature/nouvelle-fonctionnalite # Se déplacer sur une branche existante git checkout feature/nouvelle-fonctionnalite # ou (moderne, depuis Git 2.23) git switch feature/nouvelle-fonctionnalite # Créer ET se déplacer sur la nouvelle branche (raccourci) git checkout -b feature/nouvelle-fonctionnalite # ou git switch -c feature/nouvelle-fonctionnalite # Supprimer une branche (locale, déjà fusionnée) git branch -d feature/ancienne-fonctionnalite # Forcer la suppression (même non fusionnée) git branch -D feature/travail-abandonne # Renommer une branche git branch -m ancien-nom nouveau-nom
Une convention de nommage claire est essentielle dans une équipe :
# Format recommandé type/description-courte-en-kebab-case # Exemples feature/authentification-google feature/page-de-paiement fix/correction-calcul-tva fix/bug-connexion-ie11 hotfix/faille-securite-xss release/1.2.0 chore/mise-a-jour-dependances refactor/extraction-service-email docs/guide-installation
Une fois une fonctionnalité terminée, on la fusionne dans la branche principale.
# Se positionner sur la branche DESTINATION (celle qui reçoit) git switch main # Fusionner la branche source dans la branche courante git merge feature/ma-fonctionnalite
Les types de merge :
Fast-Forward Merge (fusion rapide) : quand la branche principale n’a pas avancé depuis la création de la branche feature. Git “avance” simplement le pointeur.
Avant : main : [C1] → [C2] ↓ feature : [C2] → [C3] → [C4] Après (fast-forward) : main : [C1] → [C2] → [C3] → [C4]
3-Way Merge : quand la branche principale a avancé pendant le développement de la feature. Git crée un commit de fusion.
Avant : main : [C1] → [C2] → [C5] ↓ feature : [C2] → [C3] → [C4] Après (3-way merge) : main : [C1] → [C2] → [C5] → [M] (merge commit) ↓ ↑ feature : [C2] → [C3] → [C4]
# Forcer la création d'un merge commit (même en fast-forward) git merge --no-ff feature/ma-fonctionnalite # Recommandé : permet de voir clairement l'historique des features # Merger sans créer de commit de merge (fast-forward uniquement) git merge --ff-only feature/ma-fonctionnalite # Abandonner un merge en cours git merge --abort
Le rebase “déplace” une série de commits pour qu’ils s’appliquent sur une autre base.
# Se positionner sur la branche feature git switch feature/ma-fonctionnalite # Rebaser sur main (repositionner les commits au-dessus de main) git rebase main
Différence visuelle :
Avant : main : [C1] → [C2] → [C5] → [C6] ↓ feature : [C2] → [C3] → [C4] Après git rebase main (depuis feature) : main : [C1] → [C2] → [C5] → [C6] ↓ feature : [C6] → [C3'] → [C4'] (C3 et C4 sont "rejoués" au-dessus de C6, créant C3' et C4')
Règle absolue : Ne jamais rebaser des branches partagées (comme main ou develop). Le rebase réécrit l’historique — si d’autres personnes ont basé leur travail dessus, c’est la catastrophe. Le rebase est réservé aux branches locales, non partagées.
develop
gitflow-formation
Projet GitLab ├── Overview ← Vue d'ensemble, activité récente ├── Repository ← Fichiers, branches, commits, tags │ ├── Files ← Explorateur de fichiers │ ├── Commits ← Historique des commits │ ├── Branches ← Liste des branches │ └── Tags ← Liste des tags ├── Merge Requests ← Demandes de fusion (= Pull Requests sur GitHub) ├── Issues ← Tickets de bugs et fonctionnalités ├── CI/CD ← Pipelines d'intégration continue ├── Packages & Registries ← Registry Docker, packages └── Settings ← Configuration du projet
Issues (Tickets) :
Les Issues permettent de suivre les tâches, bugs et fonctionnalités à développer.
Titre : [BUG] La page de connexion plante sur Firefox Description : ## Description La page de connexion génère une erreur JavaScript sur Firefox 121. ## Étapes pour reproduire 1. Ouvrir Firefox 2. Aller sur /login 3. Saisir des identifiants valides 4. Cliquer sur "Se connecter" ## Comportement attendu Redirection vers le tableau de bord ## Comportement observé Erreur : "Cannot read property 'token' of undefined" ## Environnement - Firefox 121.0 - Windows 11 - Production
Labels (Étiquettes) :
Catégorisez vos issues avec des labels : bug, feature, urgent, en cours, refactoring…
bug
feature
urgent
en cours
refactoring
Milestones :
Regroupez les issues par version ou sprint : v1.0.0, Sprint 5, Q1 2024
v1.0.0
Sprint 5
Q1 2024
Dans un vrai projet, on protège les branches importantes pour éviter les push directs.
Settings → Repository → Protected Branches main : - Allowed to merge: Maintainers - Allowed to push: No one (personne ne push directement sur main) - Require approval: Yes (1 approbateur minimum) develop : - Allowed to merge: Developers + Maintainers - Allowed to push: No one - Require approval: Yes
Un remote est un raccourci vers un dépôt distant. Par convention, le remote principal s’appelle origin.
# Voir les remotes configurés git remote -v # origin git@gitlab.com:alice/mon-projet.git (fetch) # origin git@gitlab.com:alice/mon-projet.git (push) # Ajouter un remote git remote add origin git@gitlab.com:alice/mon-projet.git # Changer l'URL d'un remote git remote set-url origin git@gitlab.com:alice/nouveau-nom.git # Supprimer un remote git remote remove origin # Voir les informations détaillées d'un remote git remote show origin
# Envoyer la branche courante vers origin git push # Premier push d'une nouvelle branche (définit le remote tracking) git push -u origin feature/ma-fonctionnalite # -u = --set-upstream : lie la branche locale à la distante # Après ça, git push suffit pour cette branche # Envoyer une branche spécifique git push origin main # Envoyer toutes les branches git push --all origin # Envoyer les tags git push --tags # Force push (DANGEREUX — à éviter sur les branches partagées) git push --force-with-lease # Plus sûr que --force
# Récupérer ET fusionner les modifications distantes git pull # Équivaut à : git fetch + git merge # Récupérer les modifications distantes SANS fusionner git fetch git fetch origin # Voir ce qui a changé après un fetch git log HEAD..origin/main --oneline # Pull avec rebase (recommandé pour garder un historique propre) git pull --rebase
Bonne pratique : Faites toujours un git pull avant de commencer à travailler et avant de faire un git push. Cela évite la majorité des conflits.
git pull
git push
# 1. Chaque matin : mettre à jour votre dépôt local git switch main git pull # 2. Créer une branche pour votre tâche du jour git switch -c feature/ajout-recherche # 3. Travailler... coder... tester... # 4. Sauvegarder régulièrement git add src/SearchService.java src/SearchController.java git commit -m "feat(search): ajouter le service de recherche par titre" # 5. Continuer... git add src/SearchRepository.java git commit -m "feat(search): ajouter le repository avec requête JPQL" # 6. Pousser sa branche sur GitLab git push -u origin feature/ajout-recherche # 7. Créer une Merge Request sur GitLab (voir chapitre 9) # 8. Après approbation et merge, nettoyer git switch main git pull git branch -d feature/ajout-recherche
Les tags marquent des points importants dans l’historique, généralement les versions.
# Créer un tag annoté (recommandé) git tag -a v1.0.0 -m "Version 1.0.0 — Première release publique" # Créer un tag léger (simple pointeur) git tag v1.0.0-rc1 # Voir tous les tags git tag # Voir les détails d'un tag git show v1.0.0 # Pousser les tags sur le remote git push origin v1.0.0 # Un tag spécifique git push origin --tags # Tous les tags # Créer un tag sur un commit passé git tag -a v0.9.0 -m "Version bêta" a3f2b1c # Supprimer un tag local git tag -d v1.0.0-beta # Supprimer un tag distant git push origin --delete v1.0.0-beta
GitFlow est une convention de travail (workflow) définie par Vincent Driessen en 2010. Ce n’est pas un outil Git — c’est un ensemble de règles sur comment utiliser les branches Git en équipe.
Analogie 🏭 : Imaginez une usine de production. GitFlow définit les “chaînes de montage” : quelle chaîne fait quoi, dans quel ordre, et comment les pièces passent d’une chaîne à l’autre. Sans organisation, c’est le chaos. Avec GitFlow, chaque développeur sait exactement sur quelle branche travailler.
Pourquoi GitFlow ?
Production : main ──────────────────────────────────────────────────────→ │ (tag v1.0) (tag v1.1) (tag v2.0) │ ↑ ↑ ↑ Intégration : develop ──────────────────────────────────────────────────→ ↗ ↘ ↗ ↘ ↗ ↘ Features : feat/A feat/B feat/C feat/D feat/E feat/F (abandonnée)
La structure complète :
┌─────────────────────────────────────────────────────────────┐ │ BRANCHES PERMANENTES (existent tout le temps) │ │ │ │ main ← Code en PRODUCTION, toujours stable │ │ develop ← Intégration des features pour la prochaine │ │ version (potentiellement instable) │ └─────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────┐ │ BRANCHES TEMPORAIRES (créées pour une tâche, puis supprimées) │ │ │ │ feature/* ← Nouvelles fonctionnalités │ │ release/* ← Préparation d'une nouvelle version │ │ hotfix/* ← Corrections urgentes en production │ └─────────────────────────────────────────────────────────────┘
release/*
hotfix/*
# main ne se modifie QUE par merge depuis release/* ou hotfix/* # Jamais de commit direct ! # git commit -m "..." sur main = INTERDIT
# Initialisation de develop depuis main git switch main git switch -c develop git push -u origin develop
feature/*
Règles :
feature/description-de-la-fonctionnalite
# ── DÉBUT D'UNE FEATURE ────────────────────────────────────── # 1. Se mettre à jour git switch develop git pull origin develop # 2. Créer la branche feature git switch -c feature/authentification-oauth # 3. Développer (autant de commits que nécessaire) git add . git commit -m "feat(auth): configurer le provider OAuth2 Google" git add . git commit -m "feat(auth): ajouter le controller de callback OAuth" git add . git commit -m "test(auth): ajouter les tests d'intégration OAuth" # ── FIN D'UNE FEATURE ──────────────────────────────────────── # 4. Mettre à jour depuis develop (au cas où d'autres features ont été mergées) git switch develop git pull origin develop git switch feature/authentification-oauth git merge develop # Ou git rebase develop # 5. Merger dans develop git switch develop git merge --no-ff feature/authentification-oauth # --no-ff = No Fast Forward : force la création d'un merge commit # Cela rend visible dans l'historique que cette feature a existé # 6. Pousser git push origin develop # 7. Supprimer la branche feature git branch -d feature/authentification-oauth git push origin --delete feature/authentification-oauth
Message du merge commit (généré automatiquement ou personnalisé) :
Merge branch 'feature/authentification-oauth' into develop Ajout de l'authentification via OAuth2 (Google). - Provider configuré - Callback handler - Tests d'intégration Closes #42
Quand develop contient toutes les features de la prochaine version, on crée une branche release.
release
Rôle : Préparation finale avant mise en production (corrections de bugs mineurs, mise à jour des numéros de version, documentation).
release/X.Y.Z
# ── DÉBUT D'UNE RELEASE ────────────────────────────────────── # 1. Partir de develop à jour git switch develop git pull origin develop # 2. Créer la branche release git switch -c release/1.2.0 # 3. Faire les ajustements de release # Mettre à jour le numéro de version dans pom.xml, package.json... nano pom.xml # <version>1.2.0</version> git commit -m "chore(release): passage en version 1.2.0" # Corrections de bugs mineurs découverts lors des tests finaux git commit -m "fix(ui): corriger l'alignement du footer sur mobile" git commit -m "fix(api): corriger le format de date dans les réponses" # ── FIN D'UNE RELEASE ──────────────────────────────────────── # 4. Merger dans main git switch main git merge --no-ff release/1.2.0 -m "chore(release): merge release 1.2.0 dans main" git tag -a v1.2.0 -m "Version 1.2.0" # 5. Merger dans develop (pour récupérer les corrections faites sur release) git switch develop git merge --no-ff release/1.2.0 -m "chore(release): merge release 1.2.0 dans develop" # 6. Supprimer la branche release git branch -d release/1.2.0 # 7. Pousser tout git push origin main develop --tags git push origin --delete release/1.2.0
Un bug critique est découvert en production. Il faut corriger immédiatement sans attendre la prochaine release.
hotfix/description-du-bug
# ── DÉBUT D'UN HOTFIX ──────────────────────────────────────── # 1. Partir de main (= code en production) git switch main git pull origin main # 2. Créer la branche hotfix git switch -c hotfix/faille-injection-sql # 3. Corriger le bug git commit -m "fix(security): corriger la faille d'injection SQL dans la recherche" git commit -m "test(security): ajouter le test de régression" # Mettre à jour la version (patch) nano pom.xml # <version>1.2.1</version> git commit -m "chore: passage en version 1.2.1" # ── FIN DU HOTFIX ──────────────────────────────────────────── # 4. Merger dans main git switch main git merge --no-ff hotfix/faille-injection-sql git tag -a v1.2.1 -m "Hotfix v1.2.1 — Correction faille SQL" # 5. Merger dans develop git switch develop git merge --no-ff hotfix/faille-injection-sql # 6. Supprimer la branche hotfix git branch -d hotfix/faille-injection-sql # 7. Pousser git push origin main develop --tags git push origin --delete hotfix/faille-injection-sql
time → main ──●─────────────────────────────●──────────────────●──→ │ (v1.0) │ (v1.1) │ (v1.1.1) │ │ │ └──────────────────────────────┤ │ develop ─●──────────────────────────────●──────────────────●──→ ↑ ↑ ↑ ↑ │↑ │ │ │ │ │ ││ │ feat/A ──●───● │ │ release/1.1 hotfix/fix │ feat/B feat/C │ │ │ │ ──●──● ──●──●──● │ └────────┘ │ │ (préparation v1.1)
Il existe un outil qui automatise les commandes GitFlow :
# Installation # macOS brew install git-flow-avh # Ubuntu apt-get install git-flow # Windows : inclus dans Git for Windows # Initialiser gitflow dans un dépôt git flow init # Répond aux questions : # Branch name for production releases: main # Branch name for "next release": develop # Feature branches: feature/ # Release branches: release/ # Hotfix branches: hotfix/ # Tag prefix: v # Commandes raccourcies git flow feature start authentification-oauth git flow feature finish authentification-oauth git flow release start 1.2.0 git flow release finish 1.2.0 git flow hotfix start faille-sql git flow hotfix finish faille-sql
Notre recommandation : Apprenez les commandes Git manuelles d’abord (c’est ce cours). Une fois à l’aise, l’outil git-flow est un raccourci pratique.
git-flow
Une Merge Request (MR) sur GitLab (appelée Pull Request sur GitHub) est une demande formelle de fusion d’une branche dans une autre. C’est le cœur du code review en équipe.
Le processus :
Développeur Revieweur(s) Mainteneur │ │ │ │ 1. Push la branche │ │ │ 2. Crée une MR ──────────→ │ │ │ 3. Examine le code │ │ 4. Laisse des commentaires │ │ ←──────────────── 5. Demande des modifications │ │ 6. Corrige et re-push │ │ │ ──────────────────→ 7. Approuve ──────────────→ │ │ 8. Merge la MR │ 9. Supprime la branche
Via l’interface web :
feature/authentification-oauth
# Titre : feat(auth): ajouter l'authentification OAuth2 Google ## Description Implémentation de l'authentification via Google OAuth2. ## Changements - Configuration du provider OAuth2 - Controller de callback - Service de gestion des tokens - Tests d'intégration ## Tests effectués - [x] Tests unitaires : tous passent - [x] Tests d'intégration : tous passent - [x] Test manuel sur Chrome, Firefox ## Screenshots [Si applicable, ajouter des captures d'écran] ## Issue liée Closes #42 ## Notes pour le reviewer Attention : le fichier application.properties doit avoir les clés CLIENT_ID et CLIENT_SECRET configurées dans les variables d'env GitLab.
En tant que revieweur :
# Ce qu'on vérifie dans une code review : ## Fonctionnel - Le code fait-il ce que la MR dit qu'il fait ? - Les cas limites sont-ils gérés ? - Les erreurs sont-elles traitées correctement ? ## Qualité du code - Le code est-il lisible et bien nommé ? - Y a-t-il de la duplication à factoriser ? - La complexité est-elle justifiée ? ## Tests - Y a-t-il des tests pour les nouvelles fonctionnalités ? - Les tests existants passent-ils ? ## Sécurité - Pas de secrets en dur dans le code ? - Les entrées utilisateur sont-elles validées ? - Les autorisations sont-elles vérifiées ? ## Performance - Y a-t-il des problèmes de performance évidents ?
Les types de commentaires :
# Bloquant (doit être corrigé avant merge) Cette méthode expose une faille de sécurité. La variable `userId` vient directement de la requête sans validation. # Suggestion (non bloquant) On pourrait extraire cette logique dans une méthode privée `buildEmailContent()` pour améliorer la lisibilité. # Question Pourquoi utilise-t-on une `LinkedList` ici plutôt qu'une `ArrayList` ? Est-ce intentionnel pour la performance d'insertion ? # Nit (petit détail cosmétique) init: petit espace en trop ligne 42.
GitLab reconnaît des mots-clés dans les messages de commit et de MR :
# Fermer automatiquement une issue lors du merge git commit -m "fix: corriger le bug de connexion Closes #23 Fixes #24 Resolves #25" # Mentionner une issue (sans la fermer) git commit -m "feat: début de l'implémentation Refs #42 Related to #43"
Un conflit survient quand deux modifications différentes touchent la même ligne d’un même fichier sur deux branches différentes.
Branch A modifie ligne 15 de Main.java → "String name = "Alice";" Branch B modifie ligne 15 de Main.java → "String name = "Bob";" → Git ne sait pas lequel choisir → CONFLIT
Quand Git détecte un conflit, il modifie le fichier en y insérant des marqueurs :
public class UserService { public String getGreeting(User user) { <<<<<<< HEAD ← Votre branche (branche courante) return "Bonjour " + user.getFirstName() + " !"; ======= ← Séparateur return "Bienvenue, " + user.getFullName() + " !"; >>>>>>> feature/accueil-personnalise ← La branche qu'on merge } }
Signification des marqueurs :
<<<<<<< HEAD
=======
>>>>>>> feature/accueil-personnalise
# 1. Git vous indique les fichiers en conflit git status # both modified: src/main/java/UserService.java # 2. Ouvrez le fichier et choisissez manuellement la résolution # Trois options : # A) Garder votre version (HEAD) # B) Garder la version entrante # C) Créer une version combinée (souvent la meilleure option) # Option C — version combinée (exemple) public class UserService { public String getGreeting(User user) { return "Bonjour " + user.getFullName() + " !"; // On garde "Bonjour" de HEAD et getFullName() de l'autre branche } } # 3. Supprimer TOUS les marqueurs de conflit (<<<, ===, >>>) # 4. Stager les fichiers résolus git add src/main/java/UserService.java # 5. Vérifier qu'il n'y a plus de conflits git status # 6. Terminer le merge git commit -m "merge: résolution du conflit sur UserService.getGreeting" # OU si vous aviez lancé git rebase : git rebase --continue # Abandonner la résolution si c'est trop complexe git merge --abort git rebase --abort
# Utiliser l'outil de merge intégré git mergetool # Configurer VS Code comme outil de merge git config --global merge.tool vscode git config --global mergetool.vscode.cmd 'code --wait $MERGED' # Dans VS Code : l'interface graphique propose des boutons : # "Accept Current Change" → Garder HEAD # "Accept Incoming Change" → Garder la branche entrante # "Accept Both Changes" → Garder les deux # "Compare Changes" → Voir côte à côte
# Bonnes pratiques pour minimiser les conflits : # 1. Mettre à jour régulièrement depuis develop git switch feature/ma-feature git fetch origin git merge origin/develop # ou git rebase origin/develop # 2. Communiquer en équipe sur qui travaille sur quels fichiers # 3. Faire des branches courtes (quelques jours max) # 4. Merger régulièrement les features terminées # 5. Découper les fichiers (éviter les "God classes")
CI (Continuous Integration) : À chaque push, Git lance automatiquement les tests, la compilation, et les analyses de qualité. Si quelque chose échoue, l’équipe est notifiée immédiatement.
CD (Continuous Deployment/Delivery) : Le déploiement en production (ou en environnement de test) est automatisé.
Analogie 🏭 : Imaginez une chaîne de contrôle qualité automatique. Chaque fois qu’un développeur livre du code, la chaîne s’active : elle compile le code, lance les tests, vérifie la qualité, et si tout est OK, déploie automatiquement. Plus besoin de le faire manuellement.
.gitlab-ci.yml
Toute la configuration CI/CD de GitLab se fait dans un fichier .gitlab-ci.yml à la racine du projet.
# .gitlab-ci.yml — Configuration CI/CD pour un projet Spring Boot # Image Docker de base pour tous les jobs image: maven:3.9-eclipse-temurin-17 # Les variables globales (disponibles dans tous les jobs) variables: MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" # Cache Maven pour accélérer les builds cache: paths: - .m2/repository/ # Les étapes du pipeline (s'exécutent dans l'ordre) stages: - build # Compilation - test # Tests - quality # Qualité du code - deploy # Déploiement # ──────────────────────────────────────── # STAGE : BUILD # ──────────────────────────────────────── compile: stage: build script: - mvn compile -q only: - main - develop - /^feature\/.*/ # Toutes les branches feature/* # ──────────────────────────────────────── # STAGE : TEST # ──────────────────────────────────────── unit-tests: stage: test script: - mvn test artifacts: # Conserver les rapports de test reports: junit: target/surefire-reports/*.xml paths: - target/surefire-reports/ expire_in: 1 week coverage: '/Tests run: \d+, Failures: \d+, Errors: \d+, Skipped: \d+/' # ──────────────────────────────────────── # STAGE : QUALITY # ──────────────────────────────────────── code-quality: stage: quality script: - mvn checkstyle:check allow_failure: true # Ne bloque pas le pipeline si ça échoue # ──────────────────────────────────────── # STAGE : DEPLOY # ──────────────────────────────────────── deploy-staging: stage: deploy script: - echo "Déploiement en staging..." - mvn package -DskipTests # Ici on pourrait avoir des commandes de déploiement environment: name: staging url: https://staging.mon-app.com only: - develop # Ne déploie en staging que depuis develop deploy-production: stage: deploy script: - echo "Déploiement en production..." - mvn package -DskipTests environment: name: production url: https://mon-app.com only: - main # Ne déploie en prod que depuis main when: manual # Déploiement manuel (nécessite un clic dans GitLab)
Dans GitLab : Project → CI/CD → Pipelines
Pipeline #123 passed main Alice il y a 5 min Pipeline #122 failed develop Bob il y a 2h Pipeline #121 passed feature/auth Charlie hier
En cliquant sur un pipeline, on voit chaque job et ses logs :
compile (23s) unit-tests (1m 42s) — 47 tests, 0 failures code-quality (12s) — 3 avertissements deploy-staging (45s)
Objectif : Comprendre les 3 zones de Git et créer ses premiers commits.
Énoncé :
formation-git
README.md
notes.txt
SOLUTION EXERCICE 1 :
# 1. Créer le dossier et y entrer mkdir ~/Bureau/formation-git cd ~/Bureau/formation-git # 2. Initialiser le dépôt Git git init # Initialized empty Git repository in /Users/alice/Bureau/formation-git/.git/ # 3. Créer README.md ou d'une autre façon echo "# Formation Git\nAuteur : Alicia Duponti" > README.md # 4. Stager et committer git add README.md git commit -m "docs: ajouter le fichier README avec l'auteur" # 5. Créer notes.txt echo "Mes notes sur Git :" > notes.txt echo "- Git est un système de versioning distribué" >> notes.txt # 6. Modifier README.md echo "Formation dispensée en 2026" >> README.md # 7. Stager (add) UNIQUEMENT README.md git add README.md git status # Changes to be committed: # modified: README.md # Untracked files: # notes.txt git commit -m "docs: ajouter la date de la formation dans README" # 8. Vérifier l'état git status # Untracked files: # notes.txt ← notes.txt n'est PAS dans le commit ! # 9. Afficher l'historique git log --oneline # b2c3d4e docs: ajouter la date de la formation dans README # a1b2c3d docs: ajouter le fichier README avec l'auteur
Objectif : Comprendre et utiliser .gitignore.
config/database.properties
password=secret123
logs/app.log
target/MonApp.class
src/Main.java
.log
SOLUTION EXERCICE 2 :
# 1. Créer les fichiers et dossiers # si vous ne savez pas utiliser echo, utilisez votre éditeur préféré à la place de la commande mkdir -p config logs target src echo "password=secret123" > config/database.properties echo "2024-01-15 ERROR NullPointerException" > logs/app.log echo "binary content" > target/MonApp.class echo 'public class Main { public static void main(String[] args) {} }' > src/Main.java # 2. Créer le .gitignore avec vs code ou notepad ou autre cat > .gitignore << 'EOF' # Logs — jamais dans le versioning *.log logs/ # Compilation Java target/ *.class # Fichiers de configuration sensibles config/database.properties EOF # 3. Vérifier les fichiers ignorés git status # Untracked files: # .gitignore # src/Main.java # (config/, logs/, target/ ne sont PAS listés = bien ignorés !) # Confirmation explicite git check-ignore -v config/database.properties # .gitignore:8:config/database.properties config/database.properties git check-ignore -v logs/app.log # .gitignore:3:*.log logs/app.log # 4. Committer .gitignore et src/Main.java git add .gitignore src/Main.java git commit -m "feat: ajouter le code source et configurer .gitignore" git log --oneline # c3d4e5f feat: ajouter le code source et configurer .gitignore # b2c3d4e docs: ajouter la date de la formation dans README # a1b2c3d docs: ajouter le fichier README avec l'auteur
Objectif : Créer des branches, développer en parallèle, et fusionner.
feature/page-accueil
index.html
<h1>Bienvenue</h1>
feature/page-contact
contact.html
<h1>Contactez-nous</h1>
Voici le contenu du fichier index.html :
<!DOCTYPE html> <html> <head><title>Accueil</title></head> <body><h1>Bienvenue</h1></body> </html>
Voici le fichier contact.html :
!DOCTYPE html> <html> <head><title>Contact</title></head> <body><h1>Contactez-nous</h1></body> </html>
SOLUTION EXERCICE 3 :
# 1. Branche feature/page-accueil git switch -c feature/page-accueil # 2. Créer index.html cat > index.html << 'EOF' <!DOCTYPE html> <html> <head><title>Accueil</title></head> <body><h1>Bienvenue</h1></body> </html> EOF # 3. Committer git add index.html git commit -m "feat: ajouter la page d'accueil" # 4. Revenir sur main git switch main # Vérifier : index.html n'existe pas sur main ! ls # README.md notes.txt .gitignore src/ # 5. Branche feature/page-contact git switch -c feature/page-contact # 6. Créer contact.html cat > contact.html << 'EOF' <!DOCTYPE html> <html> <head><title>Contact</title></head> <body><h1>Contactez-nous</h1></body> </html> EOF # 7. Committer git add contact.html git commit -m "feat: ajouter la page de contact" # 8. Merger feature/page-accueil dans main git switch main git merge --no-ff feature/page-accueil -m "merge: intégrer la feature page-accueil" # 9. Merger feature/page-contact dans main git merge --no-ff feature/page-contact -m "merge: intégrer la feature page-contact" # 10. Afficher le graphe git log --oneline --graph --all # * f5e6d7c merge: intégrer la feature page-contact # |\ # | * e4d5c6b feat: ajouter la page de contact # * | d3c4b5a merge: intégrer la feature page-accueil # |\ \ # | * | c2b3a49 feat: ajouter la page d'accueil # |/ / # * / b2c3d4e docs: ajouter la date de la formation # |/ # * a1b2c3d docs: ajouter le fichier README # Nettoyage des branches git branch -d feature/page-accueil feature/page-contact
Objectif : Provoquer et résoudre un conflit de merge.
presentation.txt
Bonjour, je suis Alicia.
feature/salutation-formelle
Bonjour, je suis Alicia Duponti.
Coucou, je suis Alicia !
SOLUTION EXERCICE 4 :
# 1. Créer presentation.txt sur main git switch main echo "Bonjour, je suis Alicia." > presentation.txt # 2. Committer git add presentation.txt git commit -m "docs: ajouter le fichier de présentation" # 3. Créer la branche feature git switch -c feature/salutation-formelle # 4. Modifier la présentation (version formelle) echo "Bonjour, je suis Alicia Duponti." > presentation.txt # 5. Committer git add presentation.txt git commit -m "style: ajouter le nom complet dans la présentation" # 6. Revenir sur main git switch main # 7. Modifier aussi presentation.txt sur main (version différente) echo "Coucou, je suis Alicia !" > presentation.txt # 8. Committer git add presentation.txt git commit -m "style: rendre la présentation plus décontractée" # 9. Tenter le merge → CONFLIT ! git merge feature/salutation-formelle # Auto-merging presentation.txt # CONFLICT (content): Merge conflict in presentation.txt # Automatic merge failed; fix conflicts and then commit the result. # Voir le fichier en conflit cat presentation.txt # <<<<<<< HEAD # Coucou, je suis Alice ! # ======= # Bonjour, je suis Alice Dupont. # >>>>>>> feature/salutation-formelle # 10. Résoudre : garder la version formelle avec nom complet echo "Bonjour, je suis Alicia Duponti." > presentation.txt # (On supprime tous les marqueurs de conflit) # Stager la résolution git add presentation.txt # Vérifier qu'il n'y a plus de conflits git status # All conflicts fixed but you are still merging. # (use "git commit" to conclude merge) # Créer le commit de merge git commit -m "merge: résolution conflit sur presentation.txt — version formelle retenue" # Vérifier le résultat cat presentation.txt # Bonjour, je suis Alice Dupont. git log --oneline --graph # * h7i8j9k merge: résolution conflit sur presentation.txt # |\ # | * g6h7i8j style: ajouter le nom complet dans la présentation # * | f5g6h7i style: rendre la présentation plus décontractée # |/ # * e4f5g6h docs: ajouter le fichier de présentation
Objectif : Simuler un cycle GitFlow complet avec feature, release et hotfix.
Vous travaillez sur une application “Todo List”. Appliquez GitFlow :
ajout-taches
todo.txt
suppression-taches
1.0.0
version.txt
correction-typo
v1.0.1
SOLUTION EXERCICE 5 :
# ═══════════════════════════════════════════ # INITIALISATION GITFLOW # ═══════════════════════════════════════════ mkdir todo-app && cd todo-app git init echo "# Todo App" > README.md git add README.md git commit -m "chore: initialisation du projet" # Créer develop depuis main git switch -c develop git push -u origin develop # si vous avez un remote # (Dans cet exercice local, pas de push) echo "Projet initialisé avec branches main et develop" git branch # * develop # main # ═══════════════════════════════════════════ # FEATURE : ajout-taches # ═══════════════════════════════════════════ git switch develop git switch -c feature/ajout-taches # Développement de la feature cat > todo.txt << 'EOF' === Ma liste de tâches === [ ] Apprendre Git [ ] Maîtriser GitFlow [ ] Créer un projet sur GitLab EOF git add todo.txt git commit -m "feat(todo): créer la liste de tâches initiale" # Finaliser et merger dans develop git switch develop git merge --no-ff feature/ajout-taches -m "merge: intégrer la feature ajout-taches" git branch -d feature/ajout-taches echo "Feature ajout-taches mergée dans develop" # ═══════════════════════════════════════════ # FEATURE : suppression-taches # ═══════════════════════════════════════════ git switch -c feature/suppression-taches # Ajout de la fonctionnalité cat >> todo.txt << 'EOF' [x] Configurer Git (terminé !) EOF git add todo.txt git commit -m "feat(todo): ajouter exemple de tâche complétée" # Merger dans develop git switch develop git merge --no-ff feature/suppression-taches -m "merge: intégrer la feature suppression-taches" git branch -d feature/suppression-taches # ═══════════════════════════════════════════ # RELEASE : 1.0.0 # ═══════════════════════════════════════════ git switch develop git switch -c release/1.0.0 # Ajuster la version echo "1.0.0" > version.txt git add version.txt git commit -m "chore(release): passage en version 1.0.0" # Correction mineure découverte pendant les tests sed -i 's/=== Ma liste de tâches ===/=== Todo App v1.0.0 ===/g' todo.txt git add todo.txt git commit -m "style(todo): mettre à jour le titre avec le numéro de version" # Merger dans main git switch main git merge --no-ff release/1.0.0 -m "chore(release): merger la release 1.0.0 dans main" git tag -a v1.0.0 -m "Version 1.0.0 — Première version publique de Todo App" # Merger dans develop git switch develop git merge --no-ff release/1.0.0 -m "chore(release): merger les corrections de release dans develop" # Supprimer la branche release git branch -d release/1.0.0 echo "Release 1.0.0 terminée et taguée !" # ═══════════════════════════════════════════ # HOTFIX : correction-typo # ═══════════════════════════════════════════ # Bug trouvé en production ! git switch main git switch -c hotfix/correction-typo # Corriger le bug (typo dans le titre) sed -i 's/Todo App v1.0.0/Todo App — v1.0.0/g' todo.txt git add todo.txt git commit -m "fix(todo): corriger le tiret manquant dans le titre" # Mettre à jour la version patch echo "1.0.1" > version.txt git add version.txt git commit -m "chore: passage en version 1.0.1" # Merger dans main git switch main git merge --no-ff hotfix/correction-typo -m "hotfix: corriger la typo dans le titre (v1.0.1)" git tag -a v1.0.1 -m "Version 1.0.1 — Correction de typo" # Merger dans develop git switch develop git merge --no-ff hotfix/correction-typo -m "hotfix: porter la correction de typo dans develop" # Supprimer la branche hotfix git branch -d hotfix/correction-typo # ═══════════════════════════════════════════ # RÉSULTAT FINAL # ═══════════════════════════════════════════ echo "" echo "=== Graphe final de l'historique ===" git log --oneline --graph --all # Affichage attendu : # * (HEAD -> develop) hotfix: porter la correction de typo dans develop # * merge: merger les corrections de release dans develop # |\ # | * (tag: v1.0.1, main) hotfix: corriger la typo dans le titre # | |\ # | | * fix(todo): corriger le tiret manquant dans le titre # | | * chore: passage en version 1.0.1 # | * | (tag: v1.0.0) chore(release): merger la release 1.0.0 dans main # | |\ \ # | | * | style(todo): mettre à jour le titre # | | * | chore(release): passage en version 1.0.0 # | |/ / # * | / merge: intégrer la feature suppression-taches # |\ \ \ # | * | | feat(todo): ajouter exemple de tâche complétée # * | | | merge: intégrer la feature ajout-taches # |/ / / # * / / feat(todo): créer la liste de tâches initiale # |/ / # * / chore: initialisation du projet # |/ # (= branche principale) echo "" echo "=== Tags créés ===" git tag # v1.0.0 # v1.0.1 echo "" echo "=== État de main ===" git switch main cat todo.txt # === Todo App — v1.0.0 === # [ ] Apprendre Git # [ ] Maîtriser GitFlow # [ ] Créer un projet sur GitLab # [x] Configurer Git (terminé !)
Vous allez déposer le projet Spring Boot fourni sur GitLab en appliquant GitFlow correctement.
Étape 1 — Préparer GitLab
gitflow-springboot
Étape 2 — Initialiser le dépôt local
# Dézippez le projet fourni unzip gitflow-starter.zip cd gitflow-starter # Initialisez Git git init git remote add origin git@gitlab.com:VOTRE_USERNAME/gitflow-springboot.git # Créez le .gitignore adapté à Spring Boot # (déjà présent dans le projet fourni) # Premier commit sur main git add . git commit -m "chore: initialisation du projet Spring Boot" git push -u origin main
Étape 3 — Initialiser develop
git switch -c develop git push -u origin develop
Étape 4 — Feature 1 : Page d’accueil
git switch -c feature/page-accueil # Modifier src/main/java/com/gitflow/controller/AccueilController.java # Changer le message de bienvenue # Ajouter votre prénom dans le message git add src/main/java/com/gitflow/controller/AccueilController.java git commit -m "feat(accueil): personnaliser le message de bienvenue" git push -u origin feature/page-accueil # Créer une Merge Request sur GitLab (feature/page-accueil → develop)
Étape 5 — Feature 2 : Ajout d’un endpoint
git switch develop && git pull git switch -c feature/endpoint-version # Ajouter un endpoint /api/version dans AccueilController # qui retourne { "version": "1.0.0", "auteur": "VotrePrénom" } git add . git commit -m "feat(api): ajouter l'endpoint /api/version" git push -u origin feature/endpoint-version # Créer une Merge Request sur GitLab
Étape 6 — Release 1.0.0
git switch develop && git pull git switch -c release/1.0.0 # Mettre à jour le numéro de version dans pom.xml # <version>1.0.0</version> git add pom.xml git commit -m "chore(release): passage en version 1.0.0" git push -u origin release/1.0.0 # Merge Request : release/1.0.0 → main (sur GitLab) # Merge Request : release/1.0.0 → develop (sur GitLab) # Créer le tag v1.0.0 sur GitLab (Repository → Tags)
Étape 7 — Hotfix
git switch main && git pull git switch -c hotfix/correction-description # Corriger la description dans application.properties # spring.application.name=gitflow-formation (corriger une faute) git add src/main/resources/application.properties git commit -m "fix: corriger la description de l'application" # Mettre à jour version : 1.0.1 git add pom.xml git commit -m "chore: passage en version 1.0.1" git push -u origin hotfix/correction-description # Merge Request : hotfix → main # Merge Request : hotfix → develop # Créer le tag v1.0.1
.idea/
# ── CONFIGURATION ────────────────────────────────── git config --global user.name "Prénom Nom" git config --global user.email "email@example.com" # ── INITIALISATION ───────────────────────────────── git init # Nouveau dépôt local git clone <url> # Cloner un dépôt distant # ── QUOTIDIEN ────────────────────────────────────── git status # État du dépôt git add <fichier> # Stager un fichier git add . # Stager tout git commit -m "message" # Committer git log --oneline --graph # Historique visuel git diff # Voir les modifications # ── BRANCHES ──────────────────────────────────────── git branch # Lister les branches git switch -c <branche> # Créer + aller sur la branche git switch <branche> # Changer de branche git merge --no-ff <branche> # Merger (avec commit de merge) git branch -d <branche> # Supprimer une branche # ── REMOTE ───────────────────────────────────────── git remote add origin <url> # Ajouter un remote git push -u origin <branche> # Premier push d'une branche git push # Pousser (branch déjà trackée) git pull # Récupérer et merger git fetch # Récupérer sans merger # ── ANNULATION ───────────────────────────────────── git restore <fichier> # Annuler modifs (working dir) git restore --staged <fichier> # Déstaguer git revert <hash> # Annuler un commit (safe) git stash # Mettre de côté git stash pop # Récupérer le stash # ── GITFLOW ──────────────────────────────────────── # Feature git switch develop && git pull git switch -c feature/<nom> # ... commits ... git switch develop git merge --no-ff feature/<nom> git branch -d feature/<nom> # Release git switch develop && git pull git switch -c release/<version> # ... ajustements ... git switch main && git merge --no-ff release/<version> git tag -a v<version> -m "..." git switch develop && git merge --no-ff release/<version> git branch -d release/<version> # Hotfix git switch main && git pull git switch -c hotfix/<nom> # ... correction ... git switch main && git merge --no-ff hotfix/<nom> git tag -a v<version-patch> -m "..." git switch develop && git merge --no-ff hotfix/<nom> git branch -d hotfix/<nom>