# Les commandes Git de base : init, status, add, commit, log<no value>

## Qu'allons-nous apprendre ?

Le cycle de travail quotidien avec Git, commande par commande :

| Commande | Ce qu'elle fait |
|---|---|
| `git init` | Crée un Repository |
| `git status` | Quel est l'état maintenant ? |
| `git add` | Met des modifications dans le Staging |
| `git commit` | Enregistre un instantané dans l'historique |
| `git log` | Affiche l'historique |
| `git diff` | Affiche ce qui a changé |

Et en plus : **`.gitignore`**, comment dire à Git « ignore ceux-là ».

## Pourquoi en avons-nous besoin ?

Ce sont les commandes que les développeurs lancent **des dizaines de fois par jour**. À partir de maintenant, chaque exercice et chaque projet du cours sera géré dans Git : d'abord parce que c'est une habitude professionnelle, ensuite parce que dans les projets de POO et dans le projet d'intégration, l'historique vous sauvera quand quelque chose cassera.

## Explication à partir des bases

### Le cycle de travail

```text
1. edit files          (Working Directory changes)
2. git status          (see what changed)
3. git add <files>     (choose what goes into the snapshot)
4. git commit -m "..." (save the snapshot)
5. repeat
```

### `git status` — la commande la plus importante

`git status` ne change rien. Elle vous **dit** seulement l'état : ce qui est Untracked, ce qui est Modified, ce qui est Staged. **Règle d'or : avant chaque `add` et avant chaque `commit`, lancez `git status`.**

### Le message du Commit

Le message explique **ce qui** a changé et **pourquoi**, pour celui qui lit l'historique (y compris vous dans un mois). Nous approfondirons les règles dans la leçon suivante. Pour l'instant : une phrase courte en anglais, à l'impératif : `"Add discount calculation"`, `"Fix crash on empty cart"`.

### `.gitignore`

Tous les fichiers ne doivent pas entrer dans le Repository :

- **Les fichiers créés automatiquement** : `__pycache__/`, `*.pyc`.
- **Les informations personnelles ou secrètes** : mots de passe, clés d'API, fichiers `.env`. Ils **ne doivent pas** arriver sur GitHub !
- **Les fichiers de travail locaux** : les journaux (`*.log`), une base de données locale, les environnements virtuels (`venv/`, nous les verrons dans les thèmes backend et bases de données).
- **Les fichiers système** : `.DS_Store` (Mac), `Thumbs.db` (Windows).

Un fichier nommé `.gitignore` dans le dossier du projet contient des **motifs** (une ligne par motif), et Git ne « voit » tout simplement pas les fichiers qui y correspondent.

## Syntaxe

```powershell
git init                          # create a repository in the current folder
git status                        # show the state of files
git add file.py                   # stage one file
git add folder/                   # stage everything in a folder
git add .                         # stage ALL changes in the current folder (check status first!)
git commit -m "Short message"     # commit staged changes with a message
git log                           # full history (press q to quit)
git log --oneline                 # compact history, one line per commit
git diff                          # changes NOT yet staged
git diff --staged                 # changes that ARE staged (will go into the commit)
git restore --staged file.py      # un-stage a file (keeps your edits)
```

**Un exemple de `.gitignore` pour un projet Python :**

```text
# Python cache
__pycache__/
*.pyc

# Local data and logs
*.log
*.db

# Secrets and environments
.env
venv/

# OS files
.DS_Store
Thumbs.db
```

`#` = un commentaire. `*` = « n'importe quoi ». Une ligne qui se termine par `/` = un dossier.

## Premier exemple de code

Un cycle de travail complet, à partir de zéro. Dans `kodkod6` :

```powershell
mkdir calculator
cd calculator
git init
```

Créez `calculator.py` :

```python
def add(a, b):
    return a + b
```

Et maintenant :

```powershell
git status
git add calculator.py
git status
git commit -m "Add calculator with add function"
git log --oneline
```

**Sortie :**

```text
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        calculator.py

nothing added to commit but untracked files present (use "git add" to track)
```

```text
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   calculator.py
```

```text
[main (root-commit) 4e7a1c2] Add calculator with add function
 1 file changed, 2 insertions(+)
 create mode 100644 calculator.py
```

```text
4e7a1c2 (HEAD -> main) Add calculator with add function
```

## Analyse du code ligne par ligne

| Sortie | Signification |
|---|---|
| `On branch main` | Nous sommes sur la branche principale `main`. (Les branches sont un sujet avancé, que nous ne traiterons pas pour l'instant.) |
| `No commits yet` | Le Repository est neuf, et il n'y a pas d'historique. |
| `Untracked files: calculator.py` | Git voit un nouveau fichier, mais ne le suit pas. |
| `Changes to be committed: new file` | Après `add` : le fichier est dans le Staging, et entrera dans le prochain Commit. |
| `[main (root-commit) 4e7a1c2]` | Un Commit a été créé. `root-commit` = le premier de l'historique. `4e7a1c2` = le début de son Hash. |
| `1 file changed, 2 insertions(+)` | Un résumé : un fichier, 2 lignes ajoutées. |
| `(HEAD -> main)` | **HEAD** = « où nous sommes maintenant », le dernier Commit de la branche `main`. |

**Remarquez :** `git status` lui-même suggère quoi faire (`use "git add <file>..."`). Lisez ses indications !

## Un autre exemple

**Une modification, diff, et un deuxième Commit.** Ajoutez à `calculator.py` :

```python
def subtract(a, b):
    return a - b
```

```powershell
git status
git diff
git add calculator.py
git commit -m "Add subtract function"
git log
```

**`git status` :**

```text
Changes not staged for commit:
        modified:   calculator.py
```

**`git diff` :**

```text
diff --git a/calculator.py b/calculator.py
--- a/calculator.py
+++ b/calculator.py
@@ -1,2 +1,6 @@
 def add(a, b):
     return a + b
+
+
+def subtract(a, b):
+    return a - b
```

**`git log` :**

```text
commit 9d02b6f5e1a8c7d3b4f2e6a9c0d1e8b7f6a5c4d3 (HEAD -> main)
Author: Dana Cohen <dana@example.com>
Date:   Tue Oct 6 11:20:41 2026 +0300

    Add subtract function

commit 4e7a1c2b8f0d6e5a3c1b9d7f4e2a0c8b6d5f3e1a
Author: Dana Cohen <dana@example.com>
Date:   Tue Oct 6 11:05:12 2026 +0300

    Add calculator with add function
```

**Analyse :**

- `modified:` — le fichier est **connu** de Git (il était dans un Commit), et il a changé.
- Dans `git diff`, une ligne qui commence par `+` **a été ajoutée**, une ligne avec `-` **a été supprimée**, et une ligne avec un espace est du contexte qui n'a pas changé. `@@ -1,2 +1,6 @@` = « les lignes 1 à 2 de l'ancienne version sont devenues les lignes 1 à 6 de la nouvelle ».
- `git log` affiche du plus récent au plus ancien : le Hash complet, l'auteur, la date et le message. **Pour quitter un long `git log` : la touche `q`.**

**Et maintenant `.gitignore` :** exécutez le code une fois (`python -c "import calculator"`), et `git status` affichera `__pycache__/` comme Untracked. Créez un `.gitignore` avec `__pycache__/`, et `git status` ne l'affichera plus. N'oubliez pas : `git add .gitignore` et un Commit. Le fichier lui-même **doit** être dans le Repository.

## Erreur courante

**Erreur 1 : `git add .` sans vérifier `status`.** `add .` ajoute **tout**, y compris les fichiers journaux, `__pycache__`, et pire que tout, des fichiers avec des mots de passe. **D'abord `git status`, d'abord `.gitignore`, et seulement ensuite `add .`.**

Et si vous avez ajouté quelque chose au Staging par erreur :

```powershell
git restore --staged secrets.txt
```

Le fichier sort du Staging, et les modifications qu'il contient restent.

**Erreur 2 : un Commit sans `-m`.** `git commit` seul ouvre un éditeur de texte pour le message. Si vous n'avez pas défini `core.editor`, il ouvrira généralement **Vim**, un éditeur dont il est « difficile de sortir ». Si vous êtes coincé dans Vim : `Esc`, puis tapez `:q!` et Entrée (quitter sans enregistrer), et relancez avec `-m "..."`.

**Erreur 3 : des messages sans signification.**

```text
a1b2c3d fix
e4f5a6b stuff
c7d8e9f asdf
f0a1b2c final
```

Dans un mois, personne ne comprendra ce qui s'est passé dans cet historique. Chaque Commit est « une lettre au futur ».

**Erreur 4 : ajouter à `.gitignore` un fichier déjà commité.** `.gitignore` n'affecte que les fichiers que Git **ne suit pas encore**. Si `app.log` est déjà dans le Repository, il faut aussi arrêter de le suivre : `git rm --cached app.log`, puis un Commit.

<!-- 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: Un premier Commit

Un nouveau dossier contient un fichier `calculator.py`. Écrivez la suite de commandes qui crée un Repository, vérifie l'état, ajoute le fichier et fait un premier Commit avec un message adapté.

{{< solution >}}
```powershell
git init
git status
git add calculator.py
git commit -m "Add calculator with add and subtract"
git status
```

- `git init` — crée un Repository.
- Le premier `git status` — montre que `calculator.py` est **Untracked**.
- `git add` — le déplace vers la Staging Area.
- `git commit -m` — enregistre un instantané avec un message.
- `git status` à la fin — affiche **nothing to commit, working tree clean**.
{{< /solution >}}

### Exercice 2: Lire git status

```text
Changes to be committed:
        modified:   calculator.py

Changes not staged for commit:
        modified:   README.md

Untracked files:
        notes.txt
```

Pour chaque fichier — dans quel état se trouve-t-il, et que lui arrivera-t-il si vous lancez maintenant `git commit -m "Update"` ?

{{< solution >}}
| Fichier | État | Dans le prochain Commit ? |
|---|---|---|
| `calculator.py` | La modification est dans la **Staging Area** | **Oui** |
| `README.md` | Modifié, mais **pas** ajouté avec `git add` | Non |
| `notes.txt` | **Untracked** — Git ne le suit pas du tout | Non |

Seul ce qui est dans la Staging Area entre dans le Commit.
{{< /solution >}}

### Exercice 3: .gitignore

Un projet Python contient :

```text
main.py
calculator.py
__pycache__/
secrets.txt        (passwords)
app.log
README.md
```

Écrivez un fichier `.gitignore` adapté, et expliquez pourquoi chaque ligne s'y trouve.

{{< solution >}}
```text
# Python cache
__pycache__/
*.pyc

# Passwords and keys
secrets.txt

# Logs
*.log
```

- `__pycache__/` — des fichiers que Python crée automatiquement. Il n'y a aucune raison de les garder.
- `secrets.txt` — **les mots de passe n'entrent pas dans Git**, jamais. Ce qui entre dans l'historique y reste.
- `*.log` — les journaux changent à chaque exécution et appartiennent à l'ordinateur sur lequel ils ont tourné.

`main.py`, `calculator.py` et `README.md` sont le projet lui-même — ils **entrent** bien.
{{< /solution >}}

### Exercice 4: Lire git diff

```text
-def add(a, b):
-    return a - b
+def add(a, b):
+    return a + b
```

1. Que signifient les lignes qui commencent par `-` et par `+` ?
2. Quelle est la modification réelle, et quel message de Commit lui convient ?

{{< solution >}}
1. **`-`** — une ligne qui existait et a été supprimée. **`+`** — une nouvelle ligne qui a été ajoutée.
2. La fonction `add` soustrayait au lieu d'additionner, et la modification corrige cela. Un message adapté : `Fix add returning a - b`.

`git diff` montre ce qui a changé **avant** `git add` — il vaut la peine de le lancer avant chaque Commit, pour s'assurer que seul ce que vous vouliez y entre.
{{< /solution >}}

### Exercice 5: L'historique avec git log

```text
e91d5aa Fix VAT rounding
7b2e004 Add price calculator
a3f9c21 Initial project
```

1. Quelle commande affiche l'historique avec une ligne par Commit ?
2. Quel est le Commit le plus ancien, et quel est le plus récent ?
3. Ajoutez la fonction `multiply` puis `divide`. Combien de Commits feriez-vous, et pourquoi ?

{{< solution >}}
1. `git log --oneline`.
2. Le plus ancien : `a3f9c21 Initial project` (en bas). Le plus récent : `e91d5aa Fix VAT rounding` (en haut).
3. **Deux Commits** — un pour chaque fonction : `Add multiply` puis `Add divide`. Ainsi, chaque Commit est une seule modification, et l'historique raconte une histoire claire. Si `divide` s'avère problématique, il est facile de voir exactement quand et ce qui a été ajouté.
{{< /solution >}}

<!-- exercises:end -->

## Résumé

- Le cycle : **modifier → `git status` → `git add` → `git commit -m "..."`**.
- `git status` = « quel est l'état ? ». Lancez-le avant chaque action, et lisez ses indications.
- `git log --oneline` = l'historique. `git diff` = ce qui a changé (`--staged` = ce qui entrera dans le Commit).
- `git add .` seulement après `status` et `.gitignore`. `git restore --staged` sort un fichier du Staging.
- **`.gitignore`** : `__pycache__/`, les journaux, `.env`, les secrets. Il entre lui-même dans le Repository.

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

## Documentation officielle

- [Pro Git — Getting a Git Repository](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)
- [Pro Git — Recording Changes](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository)
- [Pro Git — Viewing the Commit History](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)

<!-- docs:end -->
