Leçon 00-3 — Git et GitHub : sauvegarder, committer, pousser
1. Objectif
À la fin de cette leçon tu sauras : expliquer la différence entre sauvegarder (Ctrl+S), committer et pousser, dérouler le cycle status → add → commit → push sans notes, lire la sortie de git status, écrire un message de commit conforme au projet, et réparer un commit raté avec git commit --amend avant de le pousser.
2. Pourquoi c'est important
Deux raisons, une défensive et une offensive. Défensive : sans Git, ton travail vit dans des fichiers que le prochain faux mouvement, crash ou vol de machine peut effacer. Avec Git + GitHub, chaque étape de ton apprentissage est photographiée localement ET copiée hors site — tu ne peux plus rien perdre. Offensive : Git est l'outil n°1 du métier. Tout le code du monde professionnel passe par lui ; ton historique GitHub deviendra la preuve visible de ta progression (un an de commits réguliers dit plus qu'un CV). Dans cette méthode, Git n'est pas de l'intendance : c'est une matière, pratiquée à chaque session, dès aujourd'hui.
3. Explication simple
Git est un appareil photo pour ton projet. À chaque fois que tu le décides, il prend une photo complète de tes fichiers (un commit), la date, la signe, et lui attache ta légende (le message). Toutes les photos sont rangées dans un album caché à la racine du projet (le dossier .git/). Tu peux feuilleter l'album (git log), et revenir voir n'importe quelle photo.
GitHub est le coffre-fort hors site. C'est un site web qui héberge une copie de ton album. git push = « envoie mes nouvelles photos au coffre ». Git marche sans GitHub (l'album local suffit à l'historique) ; GitHub ajoute la sécurité (machine morte ≠ travail perdu) et le partage.
La distinction fondamentale — trois gestes, trois niveaux de sécurité :
| Geste | Ce que ça fait | Si ta machine meurt maintenant |
|---|---|---|
| Ctrl+S | écrit le fichier sur TON disque | tout est perdu |
git commit | photo dans l'album LOCAL | tout est perdu quand même |
git push | copie l'album sur GitHub | tout est sauf |
Sauvegarder n'est pas committer. Committer n'est pas pousser. Tant que tu confonds ces trois gestes, tu crois ton travail en sécurité alors qu'il ne l'est pas.
Une bonne nouvelle pour finir : le repo learnpython est déjà un dépôt Git, cloné depuis GitHub (Glypto/learnpython). Tu n'as donc PAS besoin de git init (la commande qui crée un album dans un dossier vierge) ni de configurer quoi que ce soit : l'album existe, le coffre est branché, il ne reste qu'à photographier.
4. Explication approfondie
a) Le staging : choisir ce qui entre dans la photo. Entre « fichier modifié » et « commit », Git impose une étape : la zone de staging (l'index). git add fichier veut dire « ce fichier fera partie de la prochaine photo ». Pourquoi cette étape en plus ? Parce qu'elle te permet de composer des commits propres : si tu as modifié cinq fichiers pour deux sujets différents, tu peux faire deux photos distinctes. Un fichier a donc trois états, que git status te montre en couleurs :
modifié, non stagé (rouge) → git add pour le stager
stagé (vert) → prêt pour le prochain commit
commité → dans l'album, git status n'en parle plus
b) Le cycle complet — le règlement du projet est dans GIT_WORKFLOW.md à la racine du repo (quand committer, format des messages, comment réparer). Cette leçon t'explique les concepts ; le règlement, lui, fait foi au quotidien. Le cycle :
git status # 1. TOUJOURS d'abord : qu'est-ce qui a changé ?
git add <fichiers précis> # 2. composer la photo
git status # 3. vérifier la composition
git commit -m "type: message" # 4. la photo
git push # 5. au coffre (fin de session : obligatoire)
git status avant chaque add et chaque commit : c'est gratuit et ça évite 90 % des commits ratés.
c) Le message de commit est pour toi-dans-deux-mois. Format du projet : type: description en anglais, impératif, < 60 caractères. Les types : docs:, exercises:, solutions:, project:, journal:, memory:, fix:, chore: (tableau complet dans GIT_WORKFLOW.md). update, wip, changes sont interdits : un message doit répondre à « qu'apporte ce commit ? ». Et un commit = un sujet : si le message a besoin d'un « et », c'est probablement deux commits.
d) --amend : la gomme, valable UNIQUEMENT avant push. git commit --amend remplace le dernier commit : il rouvre la photo, y intègre ce qui est stagé, et te laisse corriger le message. Cas d'usage : message raté, fichier oublié. Limite absolue : un commit déjà poussé ne s'amende pas — tu réécrirais un historique que GitHub connaît déjà, et le push suivant serait rejeté. Après push, on utilise git revert (un commit inverse — vu dans GIT_WORKFLOW.md). Règle simple à ce stade : amend avant push, jamais après.
e) .gitignore : ce que Git doit ignorer. Certains fichiers n'ont rien à faire dans l'album : caches de Python (__pycache__/), sorties générées, secrets. Le fichier .gitignore à la racine liste des motifs ; tout ce qui correspond devient invisible pour git status et git add. C'est pour ça que tu ne verras jamais __pycache__/ dans tes status alors que Python le crée : le repo l'ignore déjà. Retiens le principe : on committe les sources, pas ce qui est généré à partir d'elles.
Difficulté honnête : Git est un outil profond avec un vocabulaire aride, et les premiers jours tu exécuteras le cycle un peu mécaniquement — c'est acceptable. Ce qui doit être compris (pas récité) dès aujourd'hui : le tableau save/commit/push et la lecture de git status. Le reste (branches, revert, conflits) viendra quand tu en auras besoin ; GIT_WORKFLOW.md sert de référence permanente. Compte 2 h avec les exercices.
5. Exemples commentés
Exemple 1 — lire git status, l'état des lieux
cd ~/Claude/learnpython
git status
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
lessons/level-00-environnement/exercices/mes-reponses/hello.py
nothing added to commit but untracked files present (use "git add" to track)
Lecture ligne par ligne : tu es sur la branche main ; ta copie locale est au même niveau que GitHub (origin/main) ; un fichier est untracked (Git ne l'a jamais photographié) ; rien n'est stagé. Git te souffle même la commande suivante entre parenthèses — il le fait presque toujours.
Exemple 2 — le cycle complet sur un fichier
git add lessons/level-00-environnement/exercices/mes-reponses/hello.py
git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: lessons/level-00-environnement/exercices/mes-reponses/hello.py
Le fichier est passé en vert, section « to be committed » : il est dans la composition. On photographie, puis on vérifie :
git commit -m "exercises: complete lesson 00-1 first script"
[main 3f2a1c9] exercises: complete lesson 00-1 first script
1 file changed, 2 insertions(+)
create mode 100644 lessons/level-00-environnement/exercices/mes-reponses/hello.py
3f2a1c9 est le hash : l'identifiant unique de la photo. Et maintenant git status répond nothing to commit, working tree clean — l'état propre, celui qu'on veut retrouver en fin de session.
Exemple 3 — pousser et vérifier
git push
Enumerating objects: 9, done.
...
To https://github.com/Glypto/learnpython.git
f3bb306..3f2a1c9 main -> main
f3bb306..3f2a1c9 : GitHub est passé de l'ancien commit au tien. Preuve visuelle : ouvre https://github.com/Glypto/learnpython dans le navigateur — ton message de commit s'affiche en haut de la liste des fichiers, et hello.py est visible dans l'arborescence. Les deux premières semaines, fais cette vérification après CHAQUE push : elle ancre le lien entre la commande et la réalité.
Exemple 4 — feuilleter l'album
git log --oneline
3f2a1c9 (HEAD -> main, origin/main) exercises: complete lesson 00-1 first script
f3bb306 first commit
Une ligne par photo, la plus récente en haut. HEAD -> main = « tu es ici » ; origin/main sur la même ligne = GitHub est au même niveau (tout est poussé). Si origin/main traîne plus bas dans la liste, des commits locaux attendent un push.
Exemple 5 — réparer un commit raté avec --amend (avant push !)
git commit -m "update" # message interdit par GIT_WORKFLOW.md, oups
git commit --amend -m "exercises: add machine info script"
git log --oneline # le mauvais commit a été REMPLACÉ, pas empilé
Variante « fichier oublié » : git add le_fichier_oublie.py puis git commit --amend --no-edit (--no-edit = garder le message tel quel). Dans les deux cas le hash change : c'est une nouvelle photo qui remplace l'ancienne — d'où l'interdiction absolue après push.
6. Erreurs fréquentes
1) Croire que Ctrl+S suffit
Aucun message d'erreur — c'est bien le problème. Tu travailles trois jours, tout est « sauvegardé », puis tu découvres que rien n'est ni commité ni poussé. Symptôme mesurable : git status montre une avalanche de rouge, et git log date de la semaine dernière. Correction : le cycle, maintenant. Prévention : la routine de fin de session de GIT_WORKFLOW.md (status → commit → push, sans exception).
2) Committer sans avoir stagé
git commit -m "exercises: add hello script"
no changes added to commit (use "git add" and/or "git commit -a")
Rien n'était en vert : la photo serait vide, Git refuse. Correction : git add <fichier> d'abord. (Git propose commit -a — évite : ça stage tout d'un coup, et tu perds le contrôle de ce qui entre dans la photo.)
3) git add . aveugle depuis le mauvais dossier
git add . stage tout ce qui a changé sous le dossier courant. Lancé depuis la racine sans lire git status avant, il embarque tout et n'importe quoi (brouillons, fichiers de test) dans un commit fourre-tout. GIT_WORKFLOW.md est clair : nommer les fichiers, ou n'utiliser git add . que quand git status ne montre QUE des fichiers du même sujet. Si tu t'es raté : git restore --staged <fichier> sort un fichier du staging sans rien perdre.
4) Message de commit vide ou éditeur mystère
git commit
Sans -m, Git ouvre un éditeur (parfois Vim : écran étrange, impossible d'en sortir — Esc puis :q! + Entrée pour fuir). Prends l'habitude systématique du -m "type: message" sur une seule ligne.
5) --amend après push
git push
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/Glypto/learnpython.git'
hint: Updates were rejected because the tip of your current branch is behind
Tu as amendé un commit que GitHub connaissait : les deux historiques divergent et GitHub refuse. NE force PAS (push --force est le réflexe StackOverflow — destructeur). À ton niveau : demande de l'aide avec le contexte complet (prompt « SOS Git » de PROMPTS.md). Prévention : la règle de la section 4d, amend avant push, jamais après.
6) Taper une commande Git hors du repo
fatal: not a git repository (or any of the parent directories): .git
Git cherche un dossier .git/ dans le dossier courant ou ses parents, et n'en trouve pas : tu es hors du projet (dans ~ par exemple). Ce n'est pas grave du tout — cd ~/Claude/learnpython et c'est réglé. Même famille que « mauvais dossier » des leçons précédentes : le prompt te disait où tu étais.
7. Lire les messages d'erreur
Git ne produit pas de tracebacks Python, mais ses messages ont une structure constante et — c'est sa grande qualité — il propose presque toujours la commande de sortie. Exemple type :
fatal: not a git repository (or any of the parent directories): .git
│ │ │
│ │ └── détail : ce qu'il cherchait
│ └── le diagnostic
└── la gravité (fatal = commande annulée, rien n'a été fait)
Les trois niveaux de gravité :
hint:/ lignes entre parenthèses dansgit status→ pas une erreur, une suggestion. Ex. :(use "git add <file>..." to include...). Lis-les : Git t'écrit littéralement la commande suivante.warning:→ ça a marché, mais quelque chose mérite ton attention (ex. les fins de ligneLF will be replaced by CRLFsous Windows — bénin, ignore).error:/fatal:→ la commande n'a rien fait. Le diagnostic est dans la première ligne ; la solution, souvent dans leshint:qui suivent.
Méthode : lire la ligne fatal/error, puis TOUS les hint, avant de taper quoi que ce soit. Ne jamais enchaîner les commandes au hasard : avec Git, c'est comme ça qu'un problème bénin devient un vrai problème. En cas de doute, git status est toujours sans risque — c'est ta lampe de poche.
8. Exercices — faciles
Règles : tout se passe à la racine du repo (
cd ~/Claude/learnpython). Avant chaque commande, prédis ce quegit statusva montrer après.
a) État des lieux : git status puis git log --oneline. Note par écrit : sur quelle branche es-tu ? Combien de commits existe-t-il ? Y a-t-il des fichiers non commités (tes exercices des leçons 00-1 et 00-2, normalement) ?
b) Ton premier commit réel : stage UNIQUEMENT hello.py (leçon 00-1) en le nommant explicitement, vérifie avec git status qu'il est seul en vert, committe avec exercises: complete lesson 00-1 first script, et vérifie avec git log --oneline que ta photo est en haut de l'album.
c) Le coffre : git push, puis ouvre https://github.com/Glypto/learnpython dans le navigateur et trouve : ton message de commit, ton fichier hello.py, et son contenu affiché par GitHub. Tant que tu ne l'as pas VU en ligne, le push reste une incantation.
9. Exercices — moyens
a) Deux sujets, deux commits : tes exercices de la leçon 00-2 (fichiers de terminal-drills/, repo_map.txt…) attendent toujours. Committe-les en respectant « un commit = un sujet » : un commit pour les drills (exercises: complete lesson 00-2 terminal drills), un autre pour le mini-projet si tu l'as fait. Interdiction d'utiliser git add . : nomme tout. Puis push, et vérifie sur GitHub que les DEUX commits apparaissent.
b) L'aller-retour du staging : modifie hello.py (ajoute un print), stage-le, puis change d'avis : sors-le du staging sans perdre la modification (la commande est dans la sortie de git status — lis-la). Vérifie que le fichier est redevenu rouge et que ta modification est toujours dans le fichier. Re-stage, committe (exercises: extend hello script).
c) Détective .gitignore : ouvre le fichier .gitignore à la racine (cat .gitignore). Pour chaque motif, écris une ligne dans ton journal : ce qu'il ignore et POURQUOI on ne veut pas le committer. Puis teste : crée un fichier qui correspond à un des motifs et constate que git status ne le voit pas.
10. Exercices — difficiles
a) Le commit raté, réparé proprement — scénario complet à dérouler : (1) crée oops.py avec un print ; (2) committe-le volontairement mal : message update ET oublie de staged un deuxième fichier oops_helper.py créé en même temps ; (3) répare les DEUX problèmes avec un seul --amend : le commit final doit contenir les deux fichiers et un message conforme (exercises: add amend practice scripts) ; (4) prouve avec git log --oneline qu'il n'y a QU'UN commit (pas deux), puis push ; (5) réponds par écrit : pourquoi cette réparation aurait-elle été interdite si tu avais poussé entre les étapes 2 et 3 ?
- Indice 1 : relis la section 4d —
--amendremplace la dernière photo en y intégrant ce qui est stagé. - Indice 2 : l'ordre qui marche :
git add oops_helper.pyD'ABORD, puis un seulgit commit --amend -m "..."corrige le contenu ET le message. - Indice 3 : pour la question (5) : que connaît GitHub après un push ? Que devient cette connaissance quand le hash du commit change ? Relis l'erreur fréquente n°5.
11. Mini-projet lié — « la routine complète »
Durée cible : 20–30 min. Simule une vraie fin de session de travail, de bout en bout, en suivant la « Routine Git quotidienne » de GIT_WORKFLOW.md :
- Crée
session_recap.py: un script qui affiche 3 lignes — ce que tu as appris au niveau 00 (une phrase par leçon, en dur). - Déroule la routine :
git status→ add nominatif → re-status → commit (exercises: add level 00 recap script) → une entrée de journal si le projet en a un (commitjournal:séparé) →git push→ vérification sur github.com. - Termine par la preuve d'état propre :
git statusdoit répondrenothing to commit, working tree cleanetgit log --onelinedoit montrerorigin/mainsur le commit du haut.
Contrainte : AUCUN coup d'œil à la leçon pendant la routine — c'est le test de sortie du niveau. Si tu dois regarder, refais le mini-projet demain avec un nouveau fichier.
12. Correction / méthode de correction
Les corrections détaillées sont dans solutions/serie-00-solutions.md.
Méthode : (1) termine tout avant d'ouvrir les solutions ; (2) ici, « comparer le raisonnement » = comparer l'ordre des commandes et les sorties de git status intermédiaires — deux chemins différents vers le même historique peuvent être tous deux corrects ; (3) note dans ton journal chaque message Git qui t'a surpris, avec sa traduction en français ; (4) le vrai test : ta prochaine session de travail (niveau 01) doit se terminer par la routine complète, de mémoire.
13. À retenir
- Ctrl+S = disque, commit = album local, push = coffre GitHub. Trois gestes, trois niveaux de sécurité — seul le push met à l'abri.
- Le cycle :
status → add → status → commit → push.git statusavant tout, toujours — c'est gratuit. git addcompose la photo (staging) ; nommer les fichiers >git add ..- Message :
type: description en anglais, < 60 caractères. Un commit = un sujet. Le règlement complet vit dansGIT_WORKFLOW.md. git log --oneline: l'album ;origin/mainen haut = tout est poussé.git commit --amendrépare le dernier commit — avant push uniquement..gitignore: on committe les sources, pas ce qui est généré.- Git te souffle presque toujours la commande suivante : lis ses
hint:avant de taper au hasard.
14. Questions de révision
- Ta machine meurt à l'instant : qu'as-tu perdu si ton travail était sauvegardé ? commité ? poussé ?
- À quoi sert la zone de staging ? Pourquoi Git n'enchaîne-t-il pas directement « modifié → commité » ?
- Que signifie « untracked » dans
git status, et en quoi est-ce différent de « modified » ? - Pourquoi
git commit --amendest-il interdit après un push ? Que se passe-t-il concrètement si tu le fais ? - Cite trois types de messages de commit du projet et un exemple valide de chacun. Pourquoi
updateest-il interdit ? - Comment vois-tu, dans
git log --oneline, qu'il te reste des commits à pousser ? - Donne deux exemples de fichiers qui doivent être dans
.gitignore, et le principe général qui les relie. fatal: not a git repository: cause, diagnostic, correction — en trois phrases.
15. Checklist de compréhension
- Je peux remplir le tableau save/commit/push de mémoire, avec la colonne « si la machine meurt ».
- Je déroule le cycle complet sur un nouveau fichier sans regarder la leçon.
- Je lis
git statuset je sais dire ce qui est untracked, stagé, ou propre. - Mon premier commit réel est visible sur github.com et je l'ai vu de mes yeux.
- J'ai réparé un commit raté (message + fichier oublié) avec un seul
--amend, avant push. - Je peux expliquer à quelqu'un pourquoi on n'amende jamais après push.
- J'ai lu
GIT_WORKFLOW.mden entier et je sais que c'est là que vit le règlement.
Si une case reste vide : refais les exercices de la section correspondante demain, AVANT d'ouvrir le niveau 01.
16. Commit conseillé
Cette fois, c'est toi qui l'as déjà fait pendant les exercices — c'est tout l'objet de la leçon. S'il reste des fichiers du niveau 00 non commités :
git status
git add lessons/level-00-environnement/exercices/mes-reponses/
git commit -m "exercises: complete lesson 00-3 git basics"
git push
Puis vérifie sur github.com, entrée de journal, et direction le niveau 01.