clement13.net
Photo d’origine : Vue aérienne d’une petite rivière qui se jette dans un grand fleuve entre des rives boisées.
Description
Vue aérienne d’une petite rivière qui se jette dans un grand fleuve entre des rives boisées.
Source
Wikideas1 · page d’origine
Licence
CC0 Domaine public
Photo d’origine, non retouchée. L’arrière-plan en est une version stylisée par le site.

Git en profondeur

Comprendre le modèle objet de Git (blob, tree, commit, tag), l'index, les références et le reflog : c'est ce qui rend les commandes prévisibles.

Guide≈ 17 min de lectureVérifiéContrôle effectuéLes faits, chiffres et références ont été contrôlés au regard des sources citées dans la fiche.Rédaction assistée par IA ; sources citées en bas de page. Une erreur ? Signalez-la via le site clement13.net.Lecture
En bref
  • Comprendre le modèle objet de Git (blob, tree, commit, tag), l'index, les références et le reflog : c'est ce qui rend les commandes prévisibles.
  • Choisir entre merge, rebase, cherry-pick, revert, reset en connaissant leurs effets sur l'historique.
  • Retrouver un défaut avec bisect, récupérer un travail « perdu » avec le reflog.
  • Gérer gros fichiers et gros dépôts (LFS, partial/shallow clone, sparse-checkout), les secrets, la signature.
  • Savoir où Git sur Azure DevOps, GitHub et GitLab diffère, et ce que l'IA apporte (et ne remplace pas).
Sur cette page

Niveau : 🟢→🔴

Les bases en dix commandes#

🟢 Niveau novice

git clone <url>              # copier un dépôt (historique complet)
git status                   # où en suis-je ?
git switch -c feature/kpi    # créer et rejoindre une branche
git add chemin/fichier.sql   # préparer (indexer) une modification
git commit -m "Message"      # enregistrer localement
git fetch                    # récupérer le distant SANS toucher mon travail
git pull --rebase            # fetch + rejouer mes commits par-dessus
git push -u origin feature/kpi   # publier la branche
git log --oneline --graph --decorate   # lire l'historique
git diff / git diff --staged # voir ce qui change (non indexé / indexé)

Règle d'or du débutant : git status avant tout, git fetch plutôt que git pull quand on hésite, ne jamais réécrire une branche partagée.

✅ Bonne pratique

Configurez une fois : git config --global user.name / user.email, core.autocrlf (voir 06), pull.rebase true ou pull.ff only, init.defaultBranch main, rerere.enabled true, fetch.prune true.

Le modèle objet#

🟡 Niveau pratique

Tout est stocké dans .git/objects, par identifiant de hachage (principe). Quatre types d'objets :

Objet Contient Exemple
blob Le contenu d'un fichier (sans son nom) un script .sql
tree Une liste (mode, nom, identifiant) de blobs/trees un dossier
commit Un tree racine + parents + auteur + message un instantané
tag annoté Un pointeur nommé + signataire + message v9.1.0
commit C3 ──► tree racine ──► blob  README.md
   │                    └──► tree  Datamart/ ──► blob 010_Core.sql
   └─parent─► commit C2 ──► ...

Vérifiez par vous-même :

git cat-file -t HEAD         # commit
git cat-file -p HEAD         # affiche tree, parent, auteur, message
git cat-file -p HEAD^{tree}  # contenu du dossier racine
git ls-tree -r HEAD --name-only | head

Une branche n'est qu'un fichier de 41 octets contenant l'identifiant d'un commit (.git/refs/heads/main). Créer une branche est donc instantané et gratuit. Un commit connaît ses parents, jamais ses enfants : l'historique est un graphe orienté acyclique (DAG).

Stockage physique : objets « lâches » (zlib), puis regroupés en packfiles avec compression par deltas (git gc). Un dépôt peut sembler volumineux en historique mais compact après gc.

💡 Astuce d'expert

Un fichier renommé n'est pas stocké comme renommé : Git compare les arborescences et détecte la similarité (git log --follow, git diff -M). Si vous déplacez et réécrivez fortement un fichier dans le même commit, la détection échoue : faites deux commits.

L'index et les trois zones#

🟡 Niveau pratique

Git manipule trois zones :

 Répertoire de travail  --git add-->  Index (zone de préparation)  --git commit-->  Dépôt
        ▲                                   │                                         │
        └────────── git restore ◄───────────┘          git restore --staged ◄─────────┘

L'index est une liste de ce que sera le prochain commit. Intérêt : composer des commits propres. git add -p indexe par morceaux (hunks) ; git restore --staged désindexe ; git stash met de côté l'état de travail (équivalent d'un shelveset léger, voir 03).

git add -p script.sql        # choisir hunk par hunk
git commit -v                # voir le diff dans l'éditeur du message
git commit --fixup <sha>     # préparer une correction à intégrer
git rebase -i --autosquash origin/main
⚠️ Piège

Symptôme : « mon fichier modifié n'est pas dans le commit ». Cause : modification faite après git add. L'index garde l'ancien état. Remède : git status montre les deux listes (« à valider » / « non indexé ») ; relancer git add.

Références, HEAD et reflog#

🟡 Niveau pratique

  • Références : refs/heads/* (branches locales), refs/remotes/origin/* (suivi du distant), refs/tags/*.
  • HEAD : la position courante ; normalement une référence symbolique vers une branche. HEAD détaché : HEAD pointe un commit directement (après git checkout <sha> ou un tag). Les commits créés alors ne sont rattachés à aucune branche : créez-en une (git switch -c sauvetage) avant de quitter.
  • Notation relative : HEAD~2 (deux parents « premiers » en arrière), HEAD^2 (second parent d'une fusion), main@{yesterday}, :/texte (commit dont le message contient « texte »).

Le reflog est le journal local des déplacements de HEAD et des branches. Il sauve la mise : un reset --hard ou un rebase raté ne détruit pas les commits, ils deviennent simplement inaccessibles par une branche et sont retrouvables pendant environ 90 jours par défaut (30 jours pour les inaccessibles, ordres de grandeur de la configuration par défaut gc.reflogExpire).

git reflog                       # journal de HEAD
git reset --hard HEAD@{3}        # revenir à l'état d'il y a trois mouvements
git branch rescue <sha>          # rattacher un commit retrouvé
git fsck --lost-found            # objets orphelins
🧪 Exemple

Après un git rebase -i où l'on a supprimé par erreur une ligne, un script de migration SQL semble perdu. git reflog montre l'état avant rebase (HEAD@{5}: rebase (start)) ; git reset --hard HEAD@{6} restaure. Le reflog est local : il ne protège pas un clone supprimé.

Fusionner avec merge, rebase, cherry-pick, revert#

🟡 Niveau pratique

Opération Effet sur l'historique Quand l'utiliser Risque
merge (fast-forward) Avance simplement le pointeur Branche courte sans divergence Aucun
merge --no-ff Crée un commit de fusion à deux parents Garder la trace d'une fonctionnalité Historique plus dense
merge --squash Un seul commit sans lien de fusion Intégrer une branche « brouillon » Perte du détail ; relations de branche non tracées
rebase Rejoue vos commits sur une nouvelle base (nouveaux identifiants) Nettoyer une branche privée avant PR Réécriture : interdit sur branche partagée
cherry-pick Copie un commit ailleurs (nouvel identifiant) Rétro-porter un correctif sur une release Doublons, conflits répétés
revert Crée un commit inverse Annuler sur branche publique Fusion annulée : à gérer finement

Fusion à trois voies : Git cherche l'ancêtre commun, compare chaque branche à lui et combine. Stratégie par défaut ort (remplaçant de recursive, à vérifier selon version). Un conflit survient quand les deux côtés modifient la même zone.

git merge feature/kpi
# conflit :
git status                  # "both modified"
git diff --name-only --diff-filter=U
# éditer les marqueurs <<<<<<< ======= >>>>>>>
git add fichier && git merge --continue
git merge --abort           # renoncer
git config --global merge.conflictStyle zdiff3   # affiche aussi la base commune
git config --global rerere.enabled true          # mémorise les résolutions

Cherry-pick d'un correctif vers une branche de release :

git switch release/9.1
git cherry-pick -x abc1234     # -x ajoute "(cherry picked from ...)" : traçabilité
✅ Bonne pratique

Utilisez -x pour tout cherry-pick vers une release : l'audit retrouve l'origine. Mieux encore : corrigez d'abord sur la branche la plus ancienne concernée puis fusionnez vers l'avant (voir 05), pour que la GDS sache que le correctif est présent partout.

⚠️ Piège

Rebase d'une branche déjà poussée puis push --force : les collègues qui ont tiré l'ancienne version se retrouvent avec des commits dupliqués ou des conflits fantômes. Remède : git push --force-with-lease (refuse si le distant a avancé), uniquement sur sa branche ; règle d'équipe : jamais de force-push sur main ni sur une branche de release (protections de branche).

💡 Astuce d'expert

git rebase --onto nouvelle_base ancienne_base ma_branche transplante une branche qui était partie du mauvais point. git rebase --rebase-merges conserve la topologie des fusions. git merge-base A B donne l'ancêtre commun ; git range-diff compare deux versions d'une série de commits avant/après rebase.

Annuler avec reset, restore, revert#

🟡 Niveau pratique

Besoin Commande Remarque
Défaire le dernier commit en gardant les modifications git reset --soft HEAD~1 Index et fichiers intacts
Défaire en gardant les fichiers, vider l'index git reset --mixed HEAD~1 Défaut
Tout jeter (⚠️ destructif) git reset --hard HEAD~1 Récupérable via reflog si committé
Restaurer un fichier depuis l'index/HEAD git restore fichier Perd les modifications locales non committées
Restaurer depuis un commit git restore --source=<sha> fichier
Annuler un commit publié git revert <sha> Historique conservé
Corriger le dernier message git commit --amend Commit non encore poussé
Supprimer fichiers non suivis git clean -fdn puis -fd -n = simulation
⚠️ Piège

git reset --hard et git clean -fd détruisent les modifications non committées sans aucun filet (le reflog ne les contient pas). Habitude : git stash -u avant toute manipulation destructive.

Retrouver avec log, blame, bisect, pickaxe#

🟡 Niveau pratique

git log --oneline --graph --all --decorate -20
git log -- chemin/script.sql                  # historique d'un fichier
git log --follow -p -- chemin/script.sql      # suivre aux renommages
git log -S"DateExploitation" --oneline        # pickaxe : commits qui ajoutent/retirent la chaîne
git log -G"regex" -p                          # idem par expression régulière
git log --since="2026-09-01" --author="nom" --stat
git blame -w -C -L 120,160 script.sql         # -w ignore les espaces, -C suit les copies
git shortlog -sn --no-merges                  # contribution par auteur

git bisect automatise la recherche dichotomique du commit fautif : on désigne un commit « mauvais » et un « bon », Git propose un milieu, on teste, et ainsi de suite en O(log n).

git bisect start
git bisect bad HEAD
git bisect good v9.0.0
# Git extrait un commit : testez puis dites
git bisect good     # ou git bisect bad
# ou automatiser :
git bisect run powershell -File tests/Test-Datamart.ps1
git bisect reset
🧪 Exemple chiffré

Entre deux versions de kit, 480 commits. Bisect trouve le fautif en au plus 9 étapes (2⁹ = 512). Avec un test automatisé (consolidation d'un échantillon puis comparaison de trois totaux métier), l'opération se fait sans intervention. Condition : chaque commit doit être testable isolément (commits atomiques, pas de commit « cassé »).

Hooks#

🟡 Niveau pratique

Les hooks sont des scripts dans .git/hooks (non versionnés). Pour les partager : git config core.hooksPath .githooks et versionner le dossier, ou utiliser un gestionnaire (pre-commit, Husky, lefthook).

Hook Moment Usage
pre-commit Avant le commit Contrôle de syntaxe, encodage UTF-8/BOM, détection de secrets
commit-msg Message saisi Imposer un format (référence de ticket)
pre-push Avant le push Lancer des tests rapides
post-merge, post-checkout Après mise à jour Régénérer des artefacts
pre-receive / update (serveur) À la réception Politique côté serveur (non disponible sur tous les hébergeurs cloud)
#!/bin/sh
# .githooks/commit-msg : exige une référence de ticket
grep -Eq '^(#[0-9]+|AB#[0-9]+) ' "$1" || { echo "Message : préfixer par AB#<n° work item>"; exit 1; }
⚠️ Piège

Les hooks locaux se contournent (--no-verify) : ils sont une aide, pas une barrière. La barrière, c'est la validation côté serveur (policies de branche, pipeline obligatoire).

Sous-modules, sous-arbres, LFS#

🟡 Niveau pratique

Sous-module (git submodule) : un dépôt Git à l'intérieur d'un autre, épinglé à un commit précis. Utile pour partager une bibliothèque (une boîte à outils SQL commune) entre dépôts. Coût : clonage --recurse-submodules, mises à jour explicites, confusion fréquente.

Sous-arbre (git subtree) : copie l'historique d'un dépôt dans un sous-dossier ; pas de commande spéciale pour les consommateurs, mais historique plus lourd.

Critère Submodule Subtree Copie / package
Simplicité pour le consommateur 2/5 4/5 5/5
Traçabilité de la version 5/5 3/5 4/5
Retour de modifications vers la source 3/5 3/5 1/5

Git LFS (Large File Storage) remplace les gros fichiers par de petits pointeurs dans l'historique ; le contenu est stocké ailleurs.

git lfs install
git lfs track "*.pbix" "*.bak" "*.zip"
git add .gitattributes
git lfs ls-files
git lfs migrate import --include="*.pbix" --everything   # réécrit l'historique !
⚠️ Piège

LFS n'est pas une cure : le stockage et la bande passante sont facturés ou plafonnés par l'hébergeur ; un .pbix modifié 200 fois = 200 versions stockées. Préférez le format PBIP pour les rapports (06) et réservez LFS aux vrais binaires.

Gros dépôts, partial, shallow, sparse, monorepo#

🔴 Niveau expert

Technique Commande Effet Limite
Shallow clone git clone --depth 1 Seulement le dernier commit Historique absent : log, blame, bisect limités ; fusions difficiles
Partial clone git clone --filter=blob:none Historique complet, blobs à la demande Nécessite serveur compatible ; accès réseau ultérieur
Sparse checkout git sparse-checkout set Datamart/ Ne matérialise que certains dossiers Le dépôt reste complet (sauf partial)
Commit-graph, FSMonitor git config core.fsmonitor true, git maintenance start Accélèrent status/log Selon plateforme
Scalar scalar clone <url> Configuration prête pour gros dépôts Outil Microsoft, intégré à Git
git clone --filter=blob:none --sparse https://.../mon-produit.git
cd mon-produit
git sparse-checkout set Datamart/Datamart Reports

Monorepo ou multi-dépôts ? Le monorepo (un dépôt, plusieurs produits/modules) apporte : changements atomiques transversaux (un commit modifie SQL et rapport), un seul historique, un outillage unique. Il coûte : taille, droits non fins, builds à rendre incrémentaux. Le multi-dépôts apporte : droits et cycles indépendants ; il coûte : coordination de versions, synchronisation, « enfer des dépendances ».

🧪 Exemple BI

Un datamart (scripts SQL) et ses rapports Power BI évoluent ensemble : renommer une colonne casse les rapports. Un monorepo permet un commit/PR unique qui modifie la couche SQL et la couche sémantique ; deux dépôts imposent une PR croisée et un ordre de déploiement.

Critère Monorepo Multi-dépôts
Changements transversaux atomiques 5/5 2/5
Isolation des droits 2/5 5/5
Performance de clone 2/5 (3/5 avec partial) 5/5
Simplicité de la CI 3/5 4/5

Contexte : équipe de 5 à 30 personnes, quelques Go de contenu.

Signature des commits et des tags#

🔴 Niveau expert

L'auteur d'un commit est une simple chaîne (user.name) : on peut l'usurper. La signature cryptographique prouve l'identité du signataire.

git config --global gpg.format ssh                # signature par clé SSH (Git ≥ 2.34)
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
git config --global tag.gpgsign true
git log --show-signature -1
git tag -s v9.1.0 -m "Livraison 9.1.0"
git verify-tag v9.1.0

Choix : GPG (historique, gestion de trousseau), SSH (plus simple, déjà présent), S/MIME (certificats d'entreprise). Les plateformes affichent un badge « vérifié » ; pour une exigence réelle d'audit, imposez la signature par politique de branche (selon plateforme, à vérifier). Ne confondez pas : signature = identité ; intégrité du contenu = hachage.

✅ Bonne pratique

Signez au minimum les tags de release : ils fondent la reproductibilité d'une livraison.

Gestion des secrets#

🔴 Niveau expert

Un secret commité (mot de passe SQL, chaîne de connexion, jeton, clé d'API) est compromis même après suppression : il reste dans l'historique, les forks et les clones.

Hiérarchie de défense :

  1. Ne pas l'écrire : utiliser des variables, un coffre (Azure Key Vault), l'authentification intégrée/identité managée plutôt que des mots de passe.
  2. Empêcher le commit : .gitignore (fichiers *.local.*, *.pfx, appsettings.*.json), hook pre-commit avec un détecteur (gitleaks, detect-secrets).
  3. Détecter côté serveur : analyse de secrets de la plateforme (GitHub secret scanning/push protection, GitHub Advanced Security for Azure DevOps, proposé aussi en produits séparés Secret Protection et Code Security, réservé à Azure DevOps Services — licence à vérifier).
  4. Si fuite : révoquer et renouveler immédiatement (réécrire l'historique ne suffit jamais), puis nettoyer avec git filter-repo (outil recommandé en remplacement de filter-branch) ou BFG, puis forcer la réécriture et faire recloner l'équipe.
git filter-repo --path secrets.json --invert-paths   # retire un fichier de tout l'historique
⚠️ Piège

Réflexe erroné : « je supprime le fichier et je recommit ». Le secret reste lisible via git show <ancien sha>:fichier. Seule la rotation du secret résout le risque.

Commandes expertes#

🔴 Niveau expert

git worktree add ../hotfix release/9.0     # plusieurs répertoires, un seul dépôt
git stash push -m "wip" -- chemin/         # stash partiel
git restore -SW --source=release/9.0 -- fichier
git diff --stat main...feature             # trois points : depuis l'ancêtre commun
git log main..feature                      # deux points : ce que feature a de plus
git log --left-right --cherry-pick main...feature   # voir les commits "équivalents"
git cherry -v main feature                 # commits non encore appliqués (par patch-id)
git rev-list --count A..B
git reflog expire --expire=now --all && git gc --prune=now   # purge (irréversible)
git update-index --assume-unchanged fichier  # à éviter : masque, ne protège pas
git notes add -m "Validé recette" <sha>      # annotation hors commit
git archive --format=zip HEAD -o kit.zip     # export propre d'un état (sans .git)
git describe --tags                          # v9.1.0-14-gabc1234
git maintenance start
git config --global alias.lg "log --oneline --graph --decorate --all"

git worktree est l'arme de l'expert BI qui maintient plusieurs versions du produit : un répertoire par version (voir 05), un seul dépôt, pas de bascule de branche destructrice.

git describe produit un numéro de version lisible depuis le dernier tag : utile pour horodater un kit (kit-9.1.0-14-gabc1234).

Pièges classiques#

🔴 Niveau expert

Symptôme Cause Remède
« rejected (non-fast-forward) » au push Le distant a avancé git fetch puis pull --rebase ou merge ; pas de force
Diff « de tout le fichier » Fins de ligne ou BOM modifiés .gitattributes, core.autocrlf ; voir 06
Fichier ignoré malgré .gitignore Déjà suivi git rm --cached fichier
Branche « disparue » HEAD détaché abandonné git reflog, git branch rescue <sha>
Conflits répétés lors d'un rebase long Commits qui se chevauchent rerere, ou merge au lieu de rebase, ou squash préalable
Dépôt énorme après un import de binaires Historique conserve tout git filter-repo, LFS, git gc --aggressive (rarement utile)
Fusion « perdue » après revert d'un merge Git croit le contenu déjà fusionné Re-revert le revert avant de refusionner
Noms de fichiers « presque identiques » sur Windows Système insensible à la casse core.ignorecase, renommer en deux temps
Chemin trop long sous Windows Limite 260 caractères git config core.longpaths true, dossiers racine courts
✅ Bonne pratique

Convention de message de commit : une ligne titre de moins de 72 caractères à l'impératif, ligne vide, corps qui explique le pourquoi et pas le quoi. Référence de work item en pied (AB#12345 pour Azure Boards).

Git sur Azure DevOps, GitHub et GitLab#

🔴 Niveau expert

Capacité Azure Repos (Git) GitHub GitLab
Demande de fusion Pull request Pull request Merge request
Politiques de branche Minimum de relecteurs, build de validation, résolution des commentaires, liaison work item obligatoire Branch protection / rulesets, checks requis Branches protégées, règles d'approbation
Intégration tickets Natif avec Azure Boards (AB#) Issues, Projects Issues, boards
CI/CD Azure Pipelines (YAML) Actions GitLab CI
Hébergement sur site Azure DevOps Server GitHub Enterprise Server GitLab auto-hébergé
Droits par dossier Limités (au dépôt) ; politiques par chemin de relecteurs CODEOWNERS CODEOWNERS
IA intégrée Copilot (dans l'IDE) Copilot (PR, revue, agent) GitLab Duo

Spécificités notables :

  • Azure Repos : d'un même projet on peut avoir plusieurs dépôts Git et un dépôt TFVC (03). Les politiques de branche (reviewers, builds, liaison de work items) comblent une grande partie de ce que les check-in policies faisaient en TFVC. Plus de détails dans Azure DevOps / TFS en profondeur.
  • GitHub : écosystème le plus riche (Actions, Dependabot, code scanning, Codespaces). Les rulesets complètent les règles de protection de branche (les deux coexistent et leurs règles se cumulent ; plusieurs rulesets peuvent s'appliquer à la même branche).
  • GitLab : plateforme DevOps intégrée, bon choix si on veut l'ensemble dans un outil auto-hébergeable.
  • Dans tous les cas : protéger main, exiger PR + build, interdire le force-push, tagger les releases, sauvegarder le dépôt.

Notes /5 (contexte : équipe de 10 à 30 personnes, cycles de livraison par version, écosystème Microsoft déjà en place) :

Critère Azure Repos GitHub GitLab
Intégration avec work items Azure Boards 5/5 3/5 2/5
Richesse de l'écosystème d'extensions 3/5 5/5 4/5
Auto-hébergement pour exigences de souveraineté 4/5 4/5 5/5
Coût / licence déjà acquise 4/5 3/5 3/5

Contribution de l'IA#

🤖 IA

Cas d'usage concrets de l'IA autour de Git.

Cas d'usage Gain Risque Maturité Prérequis Garde-fous
Générer un message de commit à partir du diff 3/5 2/5 4/5 Diff petit et ciblé Relire : l'IA décrit le quoi, pas le pourquoi métier
Résumer une pull request 4/5 2/5 4/5 Plateforme avec Copilot ou équivalent Ne pas remplacer la lecture du diff
Revue de code assistée 3/5 3/5 3/5 Règles d'équipe explicites Faux négatifs ; l'IA ne connaît pas votre règle métier implicite
Suggérer une résolution de conflit 3/5 4/5 3/5 Contexte des deux branches Jamais accepter sans test : une fusion « plausible » peut inverser une règle métier
Expliquer un historique (« pourquoi cette ligne ? ») 4/5 2/5 4/5 git blame/log fournis Vérifier les hypothèses dans les tickets liés
Écrire la commande Git adaptée (reset, rebase, filter-repo) 4/5 4/5 4/5 Compréhension du modèle Commandes destructives : lire, simuler (-n), sauvegarder une branche
Rédiger les notes de version depuis les commits 4/5 2/5 4/5 Commits liés à des tickets Relecture fonctionnelle, signature de l'auteur humain

Exemples de prompts :

Voici le diff indexé (git diff --staged). Propose un message de commit en français :
titre ≤ 72 caractères à l'impératif, corps expliquant le pourquoi, sans inventer
de ticket. Si le diff mélange plusieurs sujets, dis-le et propose le découpage.
Voici le résultat de git log --oneline v9.0.0..v9.1.0 -- Datamart/.
Regroupe par thème (correctif, évolution, technique) et rédige des notes de
version pour un consultant fonctionnel. Signale les entrées ambiguës au lieu de deviner.
⚠️ Piège

Confidentialité : envoyer un diff contenant secrets, données clients ou code sous licence restrictive à un service d'IA externe. Remède : politique d'usage, modèles/instances validés par l'entreprise, détection de secrets avant l'envoi.

L'IA ne remplace pas : le jugement sur ce qui doit être commité, la responsabilité de la fusion, la recette métier des chiffres, la discipline de commits atomiques (une IA sur un commit fourre-tout produit un message fourre-tout). Voir IA et outils et la synthèse transverse.

Voir aussi#

✻ Rédigé par Claude Sonnet 5.5