Solutions — Niveau 00 (leçons 00-1, 00-2, 00-3)

Rappel de la règle d'or : on n'ouvre ce fichier qu'après avoir terminé (ou sérieusement séché sur) les manipulations. Ici, « comparer le raisonnement » veut dire comparer les commandes exactes et leur ordre — au terminal, l'ordre EST le raisonnement.


Leçon 00-1 — Installer Python et lancer son premier script

Exercice 8-a (versions)

Raisonnement — On veut deux informations : Python répond-il, et par quel chemin ? python teste le PATH, py teste le launcher Windows.

Solution

python --version
# Python 3.14.3
py --version
# Python 3.14.3

Pourquoi ça marche — Les deux commandes lancent en réalité le même interpréteur ; si les deux répondent la même version, l'installation est saine ET le PATH est correct. Si seul py répond, Python marche mais le PATH est à réparer (ou on utilise py partout).

Erreur classique sur cet exercice — Taper python -version (un seul tiret) : Python le lit comme des options séparées et affiche une erreur Argument expected for the -v option ou un comportement bizarre. Les options longues prennent DEUX tirets.

Variante plus difficilewhere python (ou which python en Git Bash) affiche le chemin complet de l'exécutable trouvé : compare-le au dossier d'installation connu.

Exercice 8-b (hello.py)

Raisonnement — Trois étapes distinctes, dans l'ordre : écrire le fichier (VS Code), sauvegarder, placer le terminal AU MÊME endroit que le fichier, lancer.

Solution

# hello.py
print("Hello, world!")
print("Python works on this machine.")
cd ~/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses
python hello.py

Pourquoi ça marchepython hello.py utilise un chemin relatif ; comme le terminal est dans le dossier du fichier, « hello.py » se résout correctement.

Erreur classique sur cet exercice — Lancer depuis ~/Claude/learnpython (la racine) : [Errno 2] No such file or directory. Le fichier existe, mais pas dans le dossier courant.

Variante plus difficile — Sans bouger le terminal de ~, lance le script avec son chemin absolu complet.

Exercice 8-c (trois scripts)

Raisonnement — L'objectif caché est la flèche haut : rappeler la commande précédente et ne modifier que le nom du fichier.

Solution

python bonjour.py     # tapée entièrement
# flèche haut, remplacer bonjour par machine :
python machine.py
# flèche haut à nouveau :
python date.py

Pourquoi ça marche — Le shell garde l'historique des commandes ; flèche haut le remonte. Modifier 3 caractères est plus rapide ET plus fiable que retaper.

Erreur classique sur cet exercice — Créer les fichiers dans le Bloc-notes et obtenir bonjour.py.txt (extension cachée par Windows). Symptôme : ls montre le vrai nom. Toujours créer les fichiers depuis VS Code ou le terminal.

Variante plus difficile — Lance les trois d'un coup : python bonjour.py && python machine.py && python date.py (&& = « puis, si ça a marché »).

Exercice 9-a (erreur de dossier volontaire)

Raisonnement — Provoquer l'erreur en connaissance de cause pour apprendre à la reconnaître : c'est une erreur du lanceur, pas du code.

Solution

cd ~/Claude/learnpython
python hello.py
# python...: can't open file 'C:\\Users\\jtron\\Claude\\learnpython\\hello.py': [Errno 2] No such file or directory

Réponses : (1) erreur du lanceur Python — le programme n'a jamais démarré, il n'y a pas de Traceback ; (2) le message contient le chemin complet où Python a cherché : ...\\Claude\\learnpython\\hello.py — c'est le dossier courant + le nom donné. Réparation sans cd :

python lessons/level-00-environnement/exercices/mes-reponses/hello.py

Pourquoi ça marche — Un chemin relatif se résout depuis le dossier courant ; en donnant le chemin complet depuis la racine du repo, la résolution tombe juste sans déplacer le terminal.

Erreur classique sur cet exercice — Relire son code en cherchant un bug : il n'y en a pas. Pas de Traceback = le code n'a pas été lu.

Variante plus difficile — Même exercice depuis ~ (deux niveaux plus haut) : reconstruis le chemin relatif complet, en t'aidant de Tab.

Exercice 9-b (REPL vs script)

Raisonnement — Faire le MÊME calcul dans les deux mondes pour toucher la différence de doigt.

Solution

>>> 60 * 60 * 24 * 7
604800
>>> exit()
# week.py
print(60 * 60 * 24 * 7)

Pourquoi ça marche — Le REPL affiche automatiquement la valeur de chaque expression tapée ; un script est muet sauf ordre explicite. La ligne nécessaire dans le script est donc le print(...).

Erreur classique sur cet exercice — Écrire 60 * 60 * 24 * 7 seul dans week.py : le script tourne sans erreur et n'affiche rien. Bug silencieux — le pire genre.

Variante plus difficile — Dans le REPL, stocke le résultat (seconds = 60 * 60 * 24 * 7) puis tape seconds : pourquoi l'assignation n'affiche-t-elle rien alors que seconds seul affiche la valeur ?

Exercice 9-c (confusion des mondes, volontaire)

Raisonnement — Provoquer les deux erreurs symétriques pour apprendre à lire le début de ligne (>>> vs $).

Solution

>>> python week.py
SyntaxError: invalid syntax
>>> exit()
$ print("test")
bash: syntax error near unexpected token `"test"'

Pourquoi ça marche — Chaque monde a sa grammaire : python week.py n'est pas du Python, print("test") n'est pas du bash. La sentinelle est le prompt.

Erreur classique sur cet exercice — Paniquer dans le REPL et fermer tout le terminal au lieu de taper exit() (ou Ctrl+D).

Variante plus difficile — Trouve UNE ligne qui est valide dans les deux mondes mais fait deux choses différentes (piste : pwd existe en bash ; dans le REPL, pwd seul donne un NameError — donc cherche plutôt du côté de lignes comme exit sans parenthèses, valide en bash ET affichant un message dans le REPL).

Exercice 10-a (sandbox et trap.py)

Raisonnement — Combiner création de dossier, écriture sans éditeur, et chemin relatif traversant : c'est la répétition générale de la leçon 00-2.

Solution

cd ~/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses
mkdir sandbox
echo 'print("trapped")' > sandbox/trap.py
python sandbox/trap.py
# trapped
python trap.py
# [Errno 2] No such file or directory

Pourquoi ça marchesandbox/trap.py dit à Python « descends dans sandbox, prends trap.py » ; trap.py seul dit « prends trap.py ICI » — et ici, il n'y est pas. La différence entre les deux commandes tient au chemin, pas au fichier.

Erreur classique sur cet exercice — Inverser les guillemets dans le echo : echo "print('trapped')" marche aussi, mais echo print("trapped") > ... sans guillemets extérieurs casse (bash interprète les parenthèses).

Variante plus difficile — Depuis sandbox/, lance un script situé dans mes-reponses/ (le parent) : il faudra .. dans le chemin (python ../hello.py).

Mini-projet 00-1 (machine_info.py)

Raisonnement — Du print en dur, mais des valeurs vraies : le but est le geste (écrire/sauver/lancer depuis trois endroits), pas le code.

Solution

# machine_info.py
print("=== Machine setup ===")
print("OS        : Windows 11")
print("Python    : 3.14.3")
print("Editor    : VS Code")
print("Terminal  : Git Bash")
print("Repo      : C:/Users/jtron/Claude/learnpython")
print("=====================")
# depuis mes-reponses/ :
python machine_info.py
# depuis la racine du repo :
python lessons/level-00-environnement/exercices/mes-reponses/machine_info.py
# depuis n'importe où (chemin absolu) :
python /c/Users/jtron/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses/machine_info.py

Pourquoi ça marche — Les trois commandes désignent le même fichier par trois chemins différents ; une fois le fichier trouvé, l'exécution est identique.

Erreur classique sur cet exercice — Mélanger les notations : un antislash Windows au milieu d'un chemin Git Bash. Choisis une notation par commande.

Variante plus difficile — Remplace les valeurs en dur par de vraies variables (os_name = "Windows 11" puis f-strings) après la leçon 01-1, et compare les deux versions.


Leçon 00-2 — Le terminal et VS Code

Exercice 8-a (GPS + tab-completion)

Raisonnement — Un terminal neuf s'ouvre dans le dossier personnel (~, soit /c/Users/jtron). Ensuite, chaque segment se complète par Tab.

Solution

pwd
# /c/Users/jtron
cd Cl<Tab>le<Tab>le<Tab>le<Tab>ex<Tab>me<Tab>
# → cd Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses/
pwd
ls

Pourquoi ça marche — Tab interroge le disque à chaque segment : s'il complète, le chemin existe. Le le<Tab> du milieu est ambigu (lessons/level-... selon le niveau où l'on est) : taper un caractère de plus lève l'ambiguïté.

Erreur classique sur cet exercice — Taper tout le chemin à la main avec une faute (enviromment) et chercher l'erreur pendant cinq minutes. Tab n'aurait jamais complété un dossier inexistant.

Variante plus difficile — Même trajet avec un seul cd et le chemin complet, puis retour à ~ avec cd sans argument (que fait cd seul ?).

Exercice 8-b (monter/descendre)

Raisonnement — Trois déplacements, dont un qui force à penser « parent du parent » : le chemin relatif remonte avant de redescendre.

Solution

cd ../../../..                                # mes-reponses → racine du repo
cd lessons/level-01-bases                     # descendre
cd ../level-00-environnement/exercices/mes-reponses   # trajet relatif final

Pourquoi ça marche — Depuis mes-reponses, il y a 4 crans jusqu'à la racine (exerciceslevel-00-environnementlessonslearnpython). Le dernier trajet remonte d'un cran (.. = lessons/) puis redescend par la branche voisine : deux dossiers frères se rejoignent toujours par leur parent commun.

Erreur classique sur cet exercice — Compter les crans de tête et se tromper : cd ../../.. laisse dans lessons/. Vérifier avec pwd après CHAQUE saut, pas à la fin.

Variante plus difficile — Refais le dernier trajet depuis level-01-bases/exercices/mes-reponses (s'il existe) : combien de .. ?

Exercice 8-c (créer dossier + fichiers)

Raisonnement — La création au terminal : mkdir pour le dossier, touch pour des fichiers vides, ls/cat pour vérifier.

Solution

mkdir terminal-drills
touch terminal-drills/a.py terminal-drills/b.py terminal-drills/notes.txt
ls terminal-drills
# a.py  b.py  notes.txt
cat terminal-drills/a.py
# (rien : le fichier est vide)
clear

Pourquoi ça marchetouch accepte plusieurs fichiers d'un coup ; cat sur un fichier vide n'affiche rien ET ne renvoie pas d'erreur — l'absence de sortie est ici la sortie attendue.

Erreur classique sur cet exercice — Faire cd terminal-drills puis oublier d'en ressortir, et créer la suite des exercices dedans (l'erreur « mauvais dossier sans s'en rendre compte » de la section 6).

Variante plus difficile — Supprime les trois fichiers puis le dossier (rm, puis rmdir) — et découvre pourquoi rmdir refuse tant que le dossier n'est pas vide.

Exercice 9-a (le chemin piégé)

Raisonnementmkdir test drive sans guillemets crée DEUX dossiers : le shell découpe sur l'espace.

Solution

mkdir test drive
ls
# ... drive/  test/       ← deux dossiers !
rmdir test drive           # supprime les deux (même découpage)
mkdir "test drive"
cd "test drive"
cd ..
rmdir "test drive"

Pourquoi ça marche — Les guillemets disent au shell « ceci est UN argument, espace compris ». Sans eux, chaque mot est un argument, et mkdir accepte plusieurs arguments (il crée un dossier par argument).

Erreur classique sur cet exercice — Essayer cd test drive (sans guillemets) pour vérifier : bash: cd: too many arguments. C'est le même piège, dans l'autre sens.

Variante plus difficile — Le même contenu avec l'échappement au lieu des guillemets : cd test\ drive (l'antislash protège l'espace).

Exercice 9-b (absolu vs relatif sur papier)

Raisonnement — Écrire les chemins AVANT de les tester force à modéliser l'arborescence de tête — c'est exactement la compétence visée.

Solution

# absolu (marche depuis partout) :
cat /c/Users/jtron/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses/hello.py
# relatif depuis la racine du repo :
cd ~/Claude/learnpython
cat lessons/level-00-environnement/exercices/mes-reponses/hello.py

Pourquoi ça marche — Le chemin absolu part de la racine du disque et ne dépend pas de la position ; le relatif dépend de pwd. Les deux cat affichent le même contenu : deux adresses, un seul fichier.

Erreur classique sur cet exercice — Tester le chemin « relatif » depuis ~ et conclure qu'il est faux : il n'est pas faux, il est relatif à un autre endroit. Un chemin relatif ne se juge qu'accompagné de son point de départ.

Variante plus difficile — Écris le chemin relatif vers hello.py DEPUIS ~/Claude/learnpython/lessons/level-01-bases (il commence par ..).

Exercice 9-c (VS Code configuré)

Raisonnement — Vérifier la chaîne complète : dossier ouvert → terminal intégré Git Bash → exécution.

Solution

cd ~/Claude/learnpython
code .

Puis dans VS Code : Ctrl+Shift+X → « Python » (Microsoft) → Install. Terminal intégré : Ctrl+ù ; si le prompt n'est pas du Git Bash ($, chemin avec ~), menu + du panneau → Select Default Profile → Git Bash → ouvrir un nouveau terminal. Enfin :

pwd
# /c/Users/jtron/Claude/learnpython
python lessons/level-00-environnement/exercices/mes-reponses/hello.py

Pourquoi ça marchecode . ouvre le dossier courant ; le terminal intégré démarre à la racine du dossier ouvert — c'est pour ça qu'ouvrir le DOSSIER (et non un fichier) change tout.

Erreur classique sur cet exercice — Ouvrir hello.py seul (double-clic depuis l'explorateur Windows) : VS Code fonctionne « en mode fichier », le terminal s'ouvre dans un dossier quelconque, et plus rien ne se comporte comme dans la leçon.

Variante plus difficile — Dans le terminal intégré, ouvre un fichier dans l'éditeur avec code lessons/README.md : le terminal peut piloter l'éditeur.

Exercice 10-a (le parcours sans filet)

Raisonnement — Tout combiner : mkdir -p (parents d'un coup), echo > (écrire sans éditeur), et quatre résolutions de chemin différentes vers le même fichier.

Solution

cd ~/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses
mkdir -p labyrinth/deep/deeper
echo 'print("way out")' > labyrinth/deep/deeper/exit.py

# 1. depuis deeper/ :
cd labyrinth/deep/deeper && python exit.py
# 2. depuis labyrinth/ :
cd ../.. && python deep/deeper/exit.py
# 3. depuis la racine du repo :
cd ~/Claude/learnpython
python lessons/level-00-environnement/exercices/mes-reponses/labyrinth/deep/deeper/exit.py
# 4. depuis ~ avec un chemin absolu :
cd ~
python /c/Users/jtron/Claude/learnpython/lessons/level-00-environnement/exercices/mes-reponses/labyrinth/deep/deeper/exit.py

Les quatre affichent way out.

Pourquoi ça marchemkdir -p crée toute la chaîne de parents manquants en une commande. Les quatre invocations ne diffèrent QUE par le chemin : plus on est loin du fichier, plus le chemin est long, jusqu'au chemin absolu qui est indépendant de la position.

Erreur classique sur cet exercicemkdir labyrinth/deep/deeper sans -p : No such file or directory (le parent labyrinth/deep n'existe pas encore ; sans -p, mkdir ne crée qu'UN niveau).

Variante plus difficile — Supprime toute la structure en une commande (rm -r labyrinth) — et explique pourquoi rm -r mérite une seconde de réflexion avant chaque usage (il ne demande pas confirmation).

Mini-projet 00-2 (repo_map.txt)

Raisonnement — La commande donne le squelette, la lecture donne les descriptions : ls -R (ou find . -maxdepth 2) + cat sur chaque README.

Solution (extrait attendu — le tien peut différer dans la formulation)

learnpython/
  README.md            <- point d'entrée : présentation de la méthode
  GIT_WORKFLOW.md      <- règlement Git : cycle, messages, réparations
  lessons/
    README.md          <- structure des niveaux, règle d'or des solutions
    TEMPLATE_LECON.md  <- les 16 sections obligatoires de chaque leçon
    level-00-environnement/   <- ce niveau : Python, terminal, Git
    level-01-bases/           <- print, variables, types, input

Pourquoi ça marchefind . -maxdepth 2 liste tout sur deux niveaux depuis la racine ; il ne reste qu'à annoter chaque ligne après lecture réelle (cat).

Erreur classique sur cet exercice — Décrire sans ouvrir (« un fichier de config », « un README ») : la consigne exigeait la preuve de lecture. La carte ne sert que si elle est vraie.

Variante plus difficile — Ajoute un troisième niveau de profondeur pour le seul dossier lessons/, et note quels dossiers sont vides à ce stade.


Leçon 00-3 — Git et GitHub

Exercice 8-a (état des lieux)

Raisonnement — Photographier l'état AVANT d'agir : branche, historique, fichiers en attente.

Solution

cd ~/Claude/learnpython
git status
git log --oneline

Réponses attendues : branche main ; un seul commit au départ (first commit) ; tes fichiers de 00-1/00-2 apparaissent en « Untracked files » (rouge).

Pourquoi ça marchegit status compare disque / staging / dernier commit ; git log liste l'album. Aucune des deux commandes ne modifie quoi que ce soit : elles sont toujours sans risque.

Erreur classique sur cet exercice — Lancer les commandes depuis ~ : fatal: not a git repository. Git se cherche un .git/ — il faut être dans le repo.

Variante plus difficilegit log sans --oneline : identifie les quatre informations de chaque commit (hash complet, auteur, date, message).

Exercice 8-b (premier commit réel)

Raisonnement — Le cycle canonique, en nommant le fichier : status → add → status → commit → log.

Solution

git status
git add lessons/level-00-environnement/exercices/mes-reponses/hello.py
git status        # hello.py seul, en vert
git commit -m "exercises: complete lesson 00-1 first script"
git log --oneline # ton commit en haut

Pourquoi ça marchegit add avec le chemin exact ne stage QUE ce fichier ; le git status intermédiaire prouve la composition avant de photographier.

Erreur classique sur cet exercicegit commit -m ... directement, sans add : no changes added to commit. La photo serait vide, Git refuse.

Variante plus difficile — Ajoute une ligne à hello.py et regarde git status : le fichier est maintenant « modified » (et non « untracked »). Explique la différence.

Exercice 8-c (push et vérification)

Raisonnement — Un push non vérifié est une incantation ; la preuve est dans le navigateur.

Solution

git push
# To https://github.com/Glypto/learnpython.git
#    f3bb306..<hash>  main -> main

Puis sur https://github.com/Glypto/learnpython : le message du commit s'affiche en haut de la liste des fichiers ; naviguer lessons → level-00-environnement → exercices → mes-reponses → hello.py affiche le code.

Pourquoi ça marchegit push envoie les commits locaux à origin (GitHub) ; le site affiche l'état du dernier commit reçu, fichier par fichier.

Erreur classique sur cet exercice — Chercher ses fichiers sur GitHub AVANT le push et croire le commit perdu : un commit est local tant qu'il n'est pas poussé — c'est tout le tableau save/commit/push.

Variante plus difficile — Sur GitHub, clique sur le message du commit : tu vois le diff (lignes ajoutées en vert). C'est exactement le contenu de la « photo ».

Exercice 9-a (deux sujets, deux commits)

Raisonnement — « Un commit = un sujet » se pratique : deux add séparés, deux commits, un seul push.

Solution

git status
git add lessons/level-00-environnement/exercices/mes-reponses/terminal-drills/
git commit -m "exercises: complete lesson 00-2 terminal drills"
git add lessons/level-00-environnement/exercices/mes-reponses/repo_map.txt
git commit -m "exercises: add repo map mini project"
git push
git log --oneline    # les deux commits, puis vérification sur github.com

Pourquoi ça marche — Le staging permet de composer chaque photo séparément, même si tous les fichiers ont changé « en même temps ». Un seul push suffit : il envoie tous les commits locaux en attente.

Erreur classique sur cet exercicegit add . qui embarque tout dans le premier commit — le second n'a plus rien à committer et l'historique est fourre-tout. C'est irréversible une fois poussé : d'où l'interdiction de l'énoncé.

Variante plus difficile — Modifie DEUX fichiers, stage-les tous les deux, puis ressors-en un (git restore --staged <fichier>) pour ne committer que l'autre.

Exercice 9-b (aller-retour du staging)

Raisonnement — La commande de sortie est écrite dans git status lui-même : apprendre à lire les hint.

Solution

# ajouter un print à hello.py, Ctrl+S, puis :
git add lessons/level-00-environnement/exercices/mes-reponses/hello.py
git status    # "Changes to be committed" + hint : use "git restore --staged"
git restore --staged lessons/level-00-environnement/exercices/mes-reponses/hello.py
git status    # redevenu rouge, "Changes not staged for commit"
cat lessons/level-00-environnement/exercices/mes-reponses/hello.py   # la modif est toujours là
git add lessons/level-00-environnement/exercices/mes-reponses/hello.py
git commit -m "exercises: extend hello script"

Pourquoi ça marchegit restore --staged ne touche QUE le staging : il retire le fichier de la composition sans modifier le fichier sur le disque. (Son cousin git restore SANS --staged écrase les modifications — à ne pas confondre.)

Erreur classique sur cet exercice — Utiliser git restore <fichier> (sans --staged) : les modifications non commitées sont détruites, sans corbeille. Lire la commande proposée par git status évitait le piège.

Variante plus difficilegit diff (modifs non stagées) vs git diff --staged (modifs stagées) : refais l'aller-retour en observant les deux à chaque étape.

Exercice 9-c (détective .gitignore)

Raisonnement — Comprendre chaque motif, puis tester empiriquement que Git ignore vraiment.

Solution

cat .gitignore
# __pycache__/   <- caches compilés générés par Python : régénérables, jamais committés
# website/dist/  <- sortie de build du site : générée depuis les sources
# (motifs exacts selon le repo)
mkdir __pycache__
touch __pycache__/fake.pyc
git status        # rien de nouveau : le dossier est invisible pour Git
rm -r __pycache__

Pourquoi ça marche — Git compare chaque chemin aux motifs du .gitignore AVANT de le lister : un fichier ignoré n'apparaît ni dans status ni dans add .. Principe commun à tous les motifs : on committe les sources, pas ce qui est généré.

Erreur classique sur cet exercice — Croire que .gitignore supprime ou cache les fichiers du disque : il ne fait qu'exclure du suivi Git. Les fichiers restent visibles avec ls.

Variante plus difficilegit status --ignored force l'affichage des fichiers ignorés : vérifie ton test avec.

Exercice 10-a (commit raté, réparé)

Raisonnement — Un --amend corrige contenu ET message en une fois, à condition de stager le fichier oublié AVANT.

Solution

echo 'print("oops")' > lessons/level-00-environnement/exercices/mes-reponses/oops.py
echo 'print("helper")' > lessons/level-00-environnement/exercices/mes-reponses/oops_helper.py
git add lessons/level-00-environnement/exercices/mes-reponses/oops.py
git commit -m "update"                 # le commit volontairement raté
git add lessons/level-00-environnement/exercices/mes-reponses/oops_helper.py
git commit --amend -m "exercises: add amend practice scripts"
git log --oneline                      # UN seul commit pour les deux fichiers
git push

Réponse à la question (5) : après un push, GitHub connaît le commit par son hash. --amend crée un commit au hash différent qui remplace l'ancien localement — les deux historiques divergent, et le push suivant est rejeté (non-fast-forward). Avant push, personne d'autre ne connaît le commit : le remplacer est sans conséquence.

Pourquoi ça marche--amend reprend le dernier commit, y fusionne le staging actuel, et remplace le message : une réparation, deux problèmes résolus, zéro commit parasite dans l'historique.

Erreur classique sur cet exercice — Faire un DEUXIÈME commit (fix: add forgotten file) au lieu d'amender : l'historique garde la trace du raté. Pas dramatique, mais l'exercice visait précisément la réparation propre.

Variante plus difficile — Amende UNIQUEMENT le message (rien de stagé) : git commit --amend -m "...". Puis amende UNIQUEMENT le contenu en gardant le message : git commit --amend --no-edit.

Mini-projet 00-3 (la routine complète)

Raisonnement — Dérouler la routine de GIT_WORKFLOW.md de mémoire ; les commandes sont connues, c'est l'enchaînement sans filet qui est évalué.

Solution

# session_recap.py
print("Lesson 00-1: run a .py file from the terminal, REPL vs script")
print("Lesson 00-2: navigate with pwd/ls/cd, relative vs absolute paths")
print("Lesson 00-3: status -> add -> commit -> push, amend before push")
git status
git add lessons/level-00-environnement/exercices/mes-reponses/session_recap.py
git status
git commit -m "exercises: add level 00 recap script"
git push
git status          # nothing to commit, working tree clean
git log --oneline   # origin/main sur le commit du haut

Pourquoi ça marche — La routine se termine sur deux preuves objectives : working tree clean (rien d'oublié sur le disque) et origin/main aligné sur HEAD (rien d'oublié en local). Ces deux vérifications closent proprement CHAQUE session de travail à partir de maintenant.

Erreur classique sur cet exercice — S'arrêter au commit et oublier le push : git log montre alors origin/main un cran plus bas que HEAD. Fin de session = push, sans exception (règle du projet).

Variante plus difficile — Ajoute l'entrée de journal de la session et committe-la séparément (journal: add level 00 completion notes) : deux sujets, deux commits — même dans la routine de clôture.