# Le contrôle de version : pourquoi on en a besoin, et les concepts de base de Git<no value>

## Qu'allons-nous apprendre ?

- Ce qu'est le **contrôle de version** (Version Control), et pourquoi chaque développeur l'utilise.
- Ce qu'est **Git**.
- Les trois zones : **Working Directory**, **Staging Area**, **Repository**.
- Ce qu'est un **Commit**.
- La configuration initiale de Git.

## Pourquoi en avons-nous besoin ?

Vous connaissez ce dossier ?

```text
project_final.py
project_final_v2.py
project_final_v2_WORKS.py
project_final_v3_dont_touch.py
project_final_v3_fixed_REALLY_FINAL.py
```

Les problèmes :

- **Quelle version fonctionne ?** Qu'est-ce qui a changé exactement entre v2 et v3 ?
- **« J'ai cassé quelque chose, et hier ça marchait ! »** Comment revenir à l'état d'hier ?
- **Le travail en équipe :** deux personnes ont modifié le même fichier. Comment combiner les modifications sans écraser ?
- **La sauvegarde :** l'ordinateur portable a été volé. Le projet est-il perdu ?

Le **contrôle de version** résout tous ces problèmes. Dans toutes les entreprises de logiciels du monde, chaque ligne de code est gérée avec lui. Sans Git, on ne peut pas travailler dans une équipe de développement, et lors d'un entretien d'embauche on s'attend à ce que vous le connaissiez.

## Explication à partir des bases

### Qu'est-ce que le contrôle de version ?

Le **contrôle de version** est un système qui **enregistre l'historique des fichiers** : chaque modification, quand elle a été faite, par qui, et pourquoi. On peut revenir à n'importe quel moment du passé, comparer des versions et combiner le travail de plusieurs personnes.

### Qu'est-ce que Git ?

**Git** est le système de contrôle de version le plus répandu au monde, de très loin. Il est :

- **Local** — tout l'historique est conservé **sur votre ordinateur**, dans un dossier caché `.git`. Il fonctionne même sans Internet.
- **Distribué** — chaque développeur possède une copie **complète** de tout l'historique.
- **Rapide et gratuit**, et écrit à l'origine par Linus Torvalds, le créateur de Linux.

**Git ≠ GitHub !** Git est **l'outil** qui tourne sur votre ordinateur. **GitHub** est **un site web** qui héberge une copie de votre Repository dans le cloud, et ajoute des outils de partage et de travail en équipe. Nous le découvrirons dans la troisième leçon.

### Repository

**Repository** (**Repo** en abrégé, « dépôt » en français) = un projet que Git suit : le dossier avec les fichiers, **plus** le dossier caché `.git` où tout l'historique est conservé.

### Commit — un instantané

**Commit** = un **instantané** enregistré du projet à un moment donné, avec :

- Un **message** qui explique ce qui a changé et pourquoi.
- Un **auteur** (nom et e-mail) et une **heure**.
- Un **identifiant unique** (Hash), par exemple `a3f9c21`.
- Une référence vers le Commit **précédent**, et c'est ainsi que se forme une **chaîne** d'historique.

```text
(a3f9c21) ◄── (7b2e004) ◄── (e91d5aa)   ← HEAD (latest)
"Initial      "Add price     "Fix VAT
 project"      calculator"    rounding"
```

{{< box "analogy" "Analogie : les points de sauvegarde d'un jeu" >}}
**Commit** = un point de sauvegarde dans un jeu vidéo. Avant le combat contre le boss, vous sauvegardez. Si vous perdez, vous revenez au point. La différence : dans Git, **chaque** point de sauvegarde reste pour toujours, avec une description, et on peut revenir à n'importe lequel ou les comparer.
{{< /box >}}

### Les trois zones

C'est le concept le plus important de la leçon. Chaque fichier du projet se trouve dans l'une de trois « zones » :

```text
 Working Directory        Staging Area            Repository (.git)
 (the files you edit)     (ready for the next     (committed history)
                           commit)
       │                        │                        │
       │──── git add ──────────►│                        │
       │                        │──── git commit ───────►│
       │◄──────────────────── (checkout / restore) ──────│
```

| Zone | Ce que c'est | Comment on y arrive |
|---|---|---|
| **Working Directory** | Le dossier dans lequel vous travaillez : les fichiers tels qu'ils sont maintenant sur le disque | Vous modifiez simplement des fichiers |
| **Staging Area** (aussi appelée Index) | Une « zone de préparation » : les modifications que vous avez choisi de mettre dans le **prochain** Commit | `git add` |
| **Repository** | L'historique enregistré : tous les Commits | `git commit` |

**Pourquoi a-t-on besoin du Staging ?** Parce qu'il arrive qu'on ait modifié 5 fichiers, mais que seuls 3 d'entre eux appartiennent à la même modification logique (« corriger un bug dans la calculatrice »). Le Staging permet de choisir **exactement** ce qui entre dans chaque Commit, pour que chaque Commit soit une unité logique.

{{< box "analogy" "Analogie : prendre une photo de groupe" >}}
**Working Directory** = toutes les personnes présentes à l'événement. **Staging Area** = les personnes que vous avez invitées à se placer devant l'appareil (« allez, toi, viens sur la photo »). **Commit** = appuyer sur le bouton : la photo est enregistrée dans l'album (Repository) pour toujours. Celui qui ne s'est pas placé devant l'appareil n'est pas sur la photo, même s'il est à l'événement.
{{< /box >}}

### Les états d'un fichier

| État | Signification |
|---|---|
| **Untracked** | Un nouveau fichier que Git ne suit pas encore |
| **Modified** | Un fichier connu qui a changé depuis le dernier Commit, mais qui n'est pas encore dans le Staging |
| **Staged** | La modification est dans le Staging, prête pour un Commit |
| **Committed** (Unmodified) | Identique au dernier Commit, « propre » |

## Syntaxe

**Installation :** Git a été installé le premier jour du cours. Vérification : `git --version`.

**Configuration unique** (une fois par ordinateur). Git enregistre le nom et l'e-mail dans chaque Commit :

```powershell
git config --global user.name "Dana Cohen"
git config --global user.email "dana@example.com"
git config --global init.defaultBranch main
git config --global core.editor "code --wait"
```

| Commande | Signification |
|---|---|
| `user.name` / `user.email` | Qui a écrit le Commit. Dans la leçon 3, le même e-mail que celui du compte GitHub. |
| `init.defaultBranch main` | La branche principale s'appellera `main` (la convention moderne). |
| `core.editor "code --wait"` | Si Git doit ouvrir un éditeur, il ouvrira VS Code. |
| `--global` | Le réglage s'applique à tous les projets de l'ordinateur. |

**Vérification :**

```powershell
git config --global --list
```

## Premier exemple de code

Voyons l'idée des « trois zones » en commandes. Dans la leçon suivante, nous détaillerons chacune en profondeur.

```powershell
mkdir ~\dev\kodkod6\git-demo
cd ~\dev\kodkod6\git-demo
git init
```

**Sortie :**

```text
Initialized empty Git repository in C:/Users/dana/dev/kodkod6/git-demo/.git/
```

Il y a maintenant un Repository. Le dossier caché `.git` a été créé. On peut le voir avec `ls -Force` (PowerShell) ou `ls -a` (Bash).

## Analyse du code ligne par ligne

| Ligne | Explication |
|---|---|
| `mkdir ...git-demo` | Un dossier ordinaire pour le projet. |
| `cd ...git-demo` | Y entrer. **Toutes les commandes Git agissent sur le Repository du dossier courant.** |
| `git init` | **init**ialize : transforme le dossier en Repository, et crée `.git` à l'intérieur. |
| `.git/` | Le « cerveau » du Repository : tous les Commits, l'historique et les réglages. **N'y touchez pas à la main.** Si vous le supprimez, tout l'historique est supprimé (les fichiers eux-mêmes restent). |

## Un autre exemple

**Le parcours d'une modification à travers les trois zones**, avec `git status` après chaque étape (tous les détails dans la leçon suivante) :

```powershell
New-Item hello.py
git status
git add hello.py
git status
git commit -m "Add hello.py"
git status
```

**Sortie (abrégée) :**

```text
Untracked files:
        hello.py

Changes to be committed:
        new file:   hello.py

[main (root-commit) 3c1f2a9] Add hello.py
 1 file changed, 0 insertions(+), 0 deletions(-)

nothing to commit, working tree clean
```

| Étape | État de `hello.py` | Zone |
|---|---|---|
| Après `New-Item` | **Untracked** | Working Directory uniquement |
| Après `git add` | **Staged** | Staging Area |
| Après `git commit` | **Committed**, et « working tree clean » | Repository |

## Erreur courante

**Erreur 1 : `git init` dans le mauvais dossier**, par exemple dans le dossier personnel (`C:\Users\dana`) ou dans un dossier qui se trouve déjà dans un autre Repository. Alors Git suit **tous** les fichiers de l'ordinateur, ou des Repositories imbriqués déroutants sont créés.

**Toujours :** `cd` vers le dossier du projet, `pwd` pour vérifier, et seulement ensuite `git init`. Et si vous vous êtes trompé : supprimez le dossier caché `.git` créé par erreur (lui seul !).

**Erreur 2 : « j'ai fait `git add`, donc c'est enregistré ».** Non ! `add` ne fait que préparer. Seul **`commit`** enregistre dans l'historique. Et une modification faite **après** le `add` n'est pas incluse, tant que vous ne refaites pas `add`.

**Erreur 3 : croire que Git sauvegarde dans le cloud.** Git est local. Si l'ordinateur portable est perdu, le Repository est perdu avec lui, sauf si vous avez fait un **push** vers GitHub (leçon 3).

**Erreur 4 : ne pas définir `user.name` / `user.email`.**

```text
Author identity unknown
*** Please tell me who you are.
```

Git refuse de faire un Commit sans savoir qui en est l'auteur. Lancez les commandes `config` ci-dessus.

<!-- exercises:start — generated by scripts/intro6/sync_site_exercises.py; edit scripts/intro6/exercises/ -->
## Exercices

Les exercices n'utilisent que ce qui a été vu dans cette leçon et les précédentes. Essayez d'abord seul, et n'ouvrez la solution qu'ensuite.

### Exercice 1: Pourquoi a-t-on besoin du contrôle de version ?

Le dossier de Danny contient ces fichiers :

```text
project_final.py
project_final_v2.py
project_final_v2_WORKS.py
project_final_v3_dont_touch.py
```

Donnez trois problèmes de cette méthode, et comment Git résout chacun d'eux.

{{< solution >}}
| Le problème | Comment Git le résout |
|---|---|
| On ne sait pas quelle est la différence entre les fichiers ni ce qui a changé dans chacun | Chaque **Commit** enregistre exactement ce qui a changé, avec un message qui explique pourquoi |
| On ne peut pas savoir quelle version est vraiment la dernière qui fonctionne | Il y a un seul historique ordonné, et **HEAD** pointe vers l'état actuel |
| Quand plusieurs personnes travaillent, chacune ajoute « une version de plus » | Tout le monde travaille sur le même **Repository**, et Git sait combiner les modifications |
{{< /solution >}}

### Exercice 2: Les trois zones

Pour chaque action — dans quelle zone se trouve la modification après elle : le Working Directory, la Staging Area ou le Repository ?

1. Vous avez modifié `calculator.py` et l'avez enregistré.
2. Vous avez lancé `git add calculator.py`.
3. Vous avez lancé `git commit -m "Add subtract"`.

{{< solution >}}
1. **Working Directory** — la modification n'existe que dans le fichier sur le disque.
2. **Staging Area** — la modification a été marquée comme faisant partie du prochain Commit.
3. **Repository** — la modification a été enregistrée comme instantané dans l'historique.
{{< /solution >}}

### Exercice 3: Première configuration

Écrivez les commandes qui définissent le nom `Dana Cohen` et l'e-mail `dana@example.com` pour Git, puis créez un nouveau Repository dans le dossier courant. Pourquoi Git a-t-il besoin d'un nom et d'un e-mail ?

{{< solution >}}
```powershell
git config --global user.name "Dana Cohen"
git config --global user.email "dana@example.com"
git init
```

Git enregistre dans chaque Commit **qui** l'a fait. Sans nom ni e-mail, Git n'acceptera pas de faire un Commit. `--global` enregistre le réglage une fois pour tous les Repositories de l'ordinateur.
{{< /solution >}}

### Exercice 4: Une chaîne de Commits

```text
(a3f9c21) <── (7b2e004) <── (e91d5aa)  <- HEAD
"Initial      "Add price     "Fix VAT
 project"      calculator"    rounding"
```

1. Que représente chacun des identifiants `a3f9c21`, `7b2e004`, `e91d5aa` ?
2. Vers quoi pointe HEAD ?
3. Pourquoi chaque Commit « pointe »-t-il vers celui qui le précède ?

{{< solution >}}
1. Ce sont des **identifiants de Commits** — chaque Commit reçoit un identifiant unique (abrégé ici).
2. **HEAD** pointe vers le Commit actuel — `e91d5aa`, « Fix VAT rounding ». C'est l'état dans lequel se trouvent maintenant les fichiers.
3. C'est ainsi que se forme un **historique** : depuis chaque Commit, on peut remonter et voir ce qui le précédait, et revenir à n'importe quel moment du passé.
{{< /solution >}}

### Exercice 5: Pourquoi a-t-on besoin d'une Staging Area ?

Aujourd'hui, vous avez changé trois choses dans le projet : vous avez corrigé un bug dans la calculatrice, amélioré le README, et ajouté un fichier de test temporaire que vous ne voulez pas garder. Comment la Staging Area aide-t-elle ici ?

{{< solution >}}
La Staging Area permet de **choisir** ce qui entre dans chaque Commit :

1. `git add calculator.py` → Commit : « Fix rounding bug in calculator ».
2. `git add README.md` → Commit : « Improve README ».
3. Le fichier de test temporaire n'est pas ajouté du tout.

Ainsi, chaque Commit est **une seule modification logique** avec un message clair — et non un mélange de tout ce que vous avez touché ce jour-là.
{{< /solution >}}

<!-- exercises:end -->

## Résumé

- Le **contrôle de version** enregistre chaque modification, et permet de revenir en arrière, de comparer et de travailler en équipe. **Git** est l'outil. **GitHub** est le site qui l'héberge dans le cloud.
- **Repository** = un projet + le dossier caché `.git` avec tout l'historique.
- **Commit** = un instantané avec un message, un auteur, une heure et un identifiant (Hash).
- Trois zones : **Working Directory** → (`git add`) → **Staging Area** → (`git commit`) → **Repository**.
- Configuration unique : `git config --global user.name` / `user.email`.

<!-- docs:start — generated by scripts/intro6/site_docs.py; edit the links there -->

## Documentation officielle

- [Pro Git — About Version Control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)
- [Pro Git — What is Git?](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F)
- [Pro Git — First-Time Git Setup](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup)

<!-- docs:end -->
