Tout ce qu'il faut savoir pour contribuer à ce repo sans tout casser, sans écraser le travail des autres, et sans laisser des traces qu'on ne veut pas. Lecture < 15 min.
Quand plusieurs personnes écrivent du code en même temps, ou qu'une seule personne écrit du code sur plusieurs semaines, on a trois problèmes :
Comment savoir qui a changé quoi, quand, et pourquoi ? Sans historique, un bug est introuvable.
Deux personnes ne peuvent pas écrire dans le même fichier en même temps sans s'écraser mutuellement.
Si ton disque crash, ou si tu casses tout, il faut pouvoir revenir à un état stable connu.
Git résout les trois en stockant le code sous forme de snapshots horodatés et signés, organisés en arbre. Chaque snapshot s'appelle un commit. GitHub est juste un serveur qui héberge cet arbre en ligne, accessible à plusieurs.
Le dossier de ton projet versionné. Reconnaissable par le sous-dossier caché .git/ à sa racine. Sans ce dossier, ce n'est plus un repo, juste un dossier normal.
Un snapshot du repo à un instant T. Identifié par un hash SHA (ex. a6ced10). Contient : qui (auteur), quand (timestamp), quoi (diff), pourquoi (message), et un pointeur vers le commit précédent (le parent). Cette chaîne de parents forme l'historique.
Un pointeur mobile vers un commit. Quand tu fais un nouveau commit sur une branche, le pointeur avance automatiquement. Les branches permettent à plusieurs lignes de travail de coexister dans le même repo.
Le pointeur spécial qui dit "voici où tu es maintenant". Quand tu fais git checkout feature/foo, HEAD pointe vers la branche feature/foo. Si tu fais un commit, HEAD ET la branche avancent ensemble.
Une copie distante du repo, typiquement sur GitHub. Par défaut elle s'appelle origin. Tu peux en avoir plusieurs (ex. un fork personnel + le repo upstream), chacun avec son propre nom.
Trois zones : tes fichiers sur le disque (working tree), ce qui est prêt à être commité (staging, alias l'index), et l'historique de commits (le repo).
git add déplace de working tree vers staging. git commit déplace de staging vers le repo.
Règle absolue de ce repo : on ne code jamais directement sur master. Master = stable, deployable. Tout passe par une branche feature, puis une PR.
# Depuis master à jour git checkout master git pull # Créer une branche feature git checkout -b feature/mon-truc # Travailler... # git add fichier.ts # git commit -m "..." # Pousser la branche sur GitHub git push -u origin feature/mon-truc
feature/xxx — nouvelle fonctionnalité (ex. feature/conseil-v1)fix/xxx — correction de bugrefactor/xxx — réorganisation sans changement de comportementdocs/xxx — documentation seulementchore/xxx — tâche d'entretien (deps, CI…).branches/Si tu travailles sur 2 features en parallèle (genre toi sur ICT et un agent IA sur la UI), tu utilises des git worktrees dans .branches/. Chaque worktree est un dossier isolé qui pointe vers une branche différente, sans interférer avec ton dossier principal.
# Créer un worktree pour une branche git worktree add .branches/feature-ict feature/ict-tuning # Maintenant .branches/feature-ict est un dossier complet # avec sa propre HEAD pointant sur feature/ict-tuning cd .branches/feature-ict # travaille ici sans toucher ton dossier principal # Quand t'as fini : git worktree remove .branches/feature-ict
Le dossier .branches/ est dans le .gitignore — il ne pollue pas l'historique.
Un bon commit, c'est une unité de changement atomique et explicable. Si tu peux pas résumer ton commit en une ligne claire, c'est qu'il est trop gros ou qu'il fait trop de choses.
<type>(<scope>): <résumé court à l'impératif> <corps optionnel, plusieurs lignes> - pourquoi ce changement - ce qui change vraiment - les pièges à connaître <footer optionnel> Co-Authored-By: ...
feat — nouvelle fonctionnalitéfix — correction de bugrefactor — réorganisation sans nouveau comportementdocs — documentation seulementchore — config, deps, CItest — tests seulementfeat(conseil): plenary 5-turn mode (all-opus) fix(charts): RSI divergence detection on flat series docs(guide): add team workflow page refactor(conseil): extract _run_attack_turn shared helper
"fix", "wip", "update". Personne ne sait ce qui change..env, clés API, mots de passe. Une fois commités, ils sont dans l'historique pour toujours.Télécharge les nouveaux commits du remote, mais ne touche PAS à ton working tree. Sans danger, à faire souvent pour voir où en sont les autres.
= fetch + merge. Récupère les commits ET les applique dans ta branche locale. Peut créer un merge commit ou des conflits.
Envoie tes commits locaux sur le remote. La première fois sur une branche : git push -u origin branch-name pour set up le tracking.
# 1. Se positionner sur master git checkout master # 2. Récupérer ce que les autres ont mergé git pull # 3. Reprendre ta branche feature et la rebaser sur master git checkout feature/mon-truc git rebase master # déplace tes commits sur la dernière version de master # 4. Travailler, commit git add . git commit -m "..." # 5. Pousser git push # ou: git push --force-with-lease si tu as rebasé
Merge garde l'historique tel quel et ajoute un commit de fusion. Tu vois les branches qui se croisent.
Rebase déplace tes commits "au-dessus" des nouveaux commits de master, comme si tu avais branché plus tard. Historique linéaire, plus propre.
Sur ce projet : on préfère rebase pour les branches feature personnelles, merge pour intégrer les PRs dans master.
Une PR est une proposition de fusionner une branche dans une autre (typiquement feature/xxx → master). C'est l'événement social du dev en équipe : tu montres ton travail, on en discute, on l'améliore, on l'accepte, on le merge.
## Summary 1-3 bullets : ce que cette PR fait, pourquoi. ## Test plan - [ ] pnpm typecheck green - [ ] pnpm test green - [ ] manuel : tester le flow X ## Concerns / followups - noter ce qui n'est PAS fait dans cette PR - les questions ouvertes 🤖 Generated with [Claude Code]
Quand une feature dépend d'une autre, tu peux stacker les PRs. Chaque PR est basée sur la précédente. GitHub re-base automatiquement quand la PR du dessous mergue.
master
└── feature/foundation ← PR #5
└── feature/conseil-v1 ← PR #6 (basé sur #5)
└── feature/conseil-v2 ← PR #7 (basé sur #6)Avantage : tu shipps en petits morceaux reviewables. Inconvénient : si #5 change pendant la review, tu dois rebaser #6 et #7.
Aucun commit direct sur master. Toujours via branche feature + PR. Master = stable et déployable, point.
pnpm typecheck et pnpm test greenuv run pytest -q greengit diff --cached pour relire)Quand tu importes du code d'un autre projet, audit anonymat obligatoire avant commit : grep pour identifiants externes (noms de projet, emails, URLs), strip-les. Voir CLAUDE.md du repo pour la checklist complète.
Avant le premier commit, vérifie git config user.name et user.email. Sur ce repo, on commit avec l'identité de l'équipe.
Plus de 3 fixes en cascade pour un même problème ? STOP. Analyse la cause racine. Ne pas patcher un patch.
Tu travailles sur une feature pendant qu'un agent IA travaille sur une autre ? Crée un worktree dans .branches/<nom>/. Jamais 2 sessions dans le même dossier — HEAD est partagé, ça casse tout.
Idéalement on attend une review humaine avant merge. Pour les sessions solo, un audit multi-agents (/review ou similaire) avant gros merge.
git push --force origin master peut effacer du travail des autres définitivement. À ne JAMAIS faire. Si tu vois un comportement bizarre, parle à quelqu'un, ne force pas.
Préférer --force-with-lease qui refuse si quelqu'un a poussé entre-temps, et uniquement sur tes propres branches feature.
Si tu commits sur master par erreur sans avoir pushé :
# Crée une branche feature à partir d'où tu es git branch feature/recuperation # Reset master à origin/master git reset --hard origin/master # Continue sur feature/recuperation git checkout feature/recuperation
Quand deux branches modifient les mêmes lignes, git ne peut pas choisir. Il marque les conflits dans les fichiers :
<<<<<<< HEAD ta version ======= la version de l'autre branche >>>>>>> master
Tu édites le fichier, gardes ce qui doit rester, supprimes les marqueurs <<< / === / >>>, puis git add + git commit pour finaliser.
.env, clés API, mots de passe — une fois dans l'historique, ils sont publics même si tu les supprimes ensuite. Solution : force-push avec history rewrite (destructif, dernier recours) ou révoquer la clé immédiatement.
Préventif : .gitignore avec .env*, et git diff --cached avant chaque commit.
Git garde TOUT en mémoire pendant 90 jours, même les commits "perdus". git reflog liste tous les mouvements de HEAD. Tu peux toujours revenir en arrière.
git reflog # liste tous les mouvements HEAD
git reset --hard HEAD@{5} # revient à l'état n°5 dans la liste# === État === git status # qu'est-ce qui change ? git log --oneline -10 # 10 derniers commits git diff # diff non-staged git diff --cached # diff staged (prêt à committer) git branch # liste des branches locales git branch -a # + branches distantes # === Travailler === git checkout master # aller sur master git pull # récupérer les derniers commits git checkout -b feature/xxx # nouvelle branche git add fichier.ts # stager un fichier git add . # stager tout (attention secrets !) git commit -m "feat(scope): message" # commit git push # pousser git push -u origin feature/xxx # premier push d'une branche # === Synchroniser === git fetch # voir ce qu'il y a sur le remote git pull # fetch + merge git pull --rebase # fetch + rebase git rebase master # rebaser ta branche sur master # === GitHub CLI === gh pr create # ouvrir une PR gh pr list # lister les PRs gh pr view 5 # voir la PR #5 gh pr merge 5 # merger la PR #5 gh pr checks # voir le statut CI # === Récupération === git reflog # historique des mouvements HEAD git stash # mettre tes changements de côté git stash pop # les remettre git reset --soft HEAD~1 # annuler le dernier commit (garde les changements) git restore fichier.ts # annuler les modifs sur un fichier # === Worktrees (sessions parallèles) === git worktree add .branches/foo feature/bar # checkout feature/bar dans .branches/foo git worktree list # voir tous les worktrees git worktree remove .branches/foo # supprimer
brew install gh) — interaction GitHub depuis le terminal. Indispensable.