# GitHub, Remote et Push — et de bons messages de Commit<no value>

## Qu'allons-nous apprendre ?

- Ce qu'est **GitHub**.
- Ce qu'est un **Remote** (un serveur distant) et ce qu'est **origin**.
- Comment **envoyer** du code avec **`git push`**.
- Comment écrire de bons **messages de Commit**.

## Pourquoi en avons-nous besoin ?

Jusqu'à présent, tout l'historique est enregistré **uniquement sur votre ordinateur**. GitHub apporte :

- **Une sauvegarde dans le cloud** — l'ordinateur portable est cassé ? Le code est en sécurité.
- **Le partage** — vous envoyez un lien au formateur, à vos coéquipiers, à un employeur.
- **Un portfolio** — votre profil GitHub est le CV professionnel d'un développeur. Les recruteurs le regardent **vraiment**.
- **Le travail en équipe** — toute l'équipe synchronise le code via le même Repository.

À partir d'aujourd'hui, chaque projet du cours (y compris les projets de POO et le projet d'intégration) est envoyé sur GitHub.

## Explication à partir des bases

### GitHub

**GitHub** est un site web (et un service) qui héberge des Repositories Git **sur un serveur**. C'est un **serveur** au sens que nous avons appris dans le thème sur l'ordinateur, le système d'exploitation et le réseau : votre Git local est le **client**, et il envoie les Commits à GitHub en **HTTPS**.

(Il existe aussi des services similaires : GitLab et Bitbucket. L'idée est la même.)

### Remote et origin

**Remote** = l'adresse d'**une autre copie** du Repository qui se trouve ailleurs, généralement sur GitHub. On donne un **surnom** à un Remote, et par convention, le Remote principal s'appelle **`origin`**.

```text
Your computer                              GitHub
┌──────────────────────┐   git push    ┌──────────────────────┐
│ Local repository     │ ────────────► │ Remote repository    │
│ (.git, all commits)  │               │ "origin"             │
└──────────────────────┘ ◄──────────── └──────────────────────┘
                           git pull
```

- **`git push`** — **envoie** les Commits locaux qui ne sont pas encore sur le Remote.
- **`git pull`** — **télécharge** les nouveaux Commits du Remote (quand quelqu'un d'autre a fait un push, ou quand vous avez travaillé depuis un autre ordinateur). Nous ne l'approfondirons pas pour l'instant.
- **`git clone <url>`** — télécharge sur l'ordinateur un Repository **existant** de GitHub, avec tout son historique.

{{< box "analogy" "Analogie : un album photo et une sauvegarde dans le cloud" >}}
Le Repository local est l'album photo de votre téléphone. **`commit`** = prendre une photo (enregistrée sur le téléphone). **`push`** = synchroniser avec le cloud. Si le téléphone est perdu, les photos synchronisées sont en sécurité, et celles qui ne l'étaient pas sont perdues. Donc : **commitez souvent, faites un push à la fin de chaque unité de travail.**
{{< /box >}}

### L'authentification

GitHub doit savoir que vous avez le droit de faire un push vers le Repository. Sous Windows et Mac, lors du premier push, **une fenêtre de connexion s'ouvre dans le navigateur** (Git Credential Manager), vous vous connectez une fois, et le système s'en souvient. **GitHub n'accepte pas le mot de passe du compte dans le terminal**. Si on vous demande un « Password » dans le terminal, il vous faut un **Personal Access Token** (nous le verrons dans les erreurs courantes).

### De bons messages de Commit

| Règle | ✗ Pas comme ça | ✓ Comme ça |
|---|---|---|
| **Impératif, présent** (« ce que fait le Commit ») | `Added login` | `Add login form` |
| **Précis** | `fix bug` | `Fix crash when cart is empty` |
| **Court** (la première ligne jusqu'à ~50 caractères) | `I changed the function that calculates the total because...` | `Apply VAT after discount in total` |
| **Une seule modification logique** | `Add login, fix typos, update colors` | Trois Commits séparés |
| **En anglais** (la convention du secteur) | | |

**Test :** complétez la phrase « If applied, this commit will **___** ». `Add login form` ✓. `Added login` ✗.

## Syntaxe

**Relier un Repository local existant à GitHub et le premier push :**

```powershell
git remote add origin https://github.com/USERNAME/REPO-NAME.git
git branch -M main
git push -u origin main
```

**Ensuite, à chaque fois :**

```powershell
git add ...
git commit -m "..."
git push
```

**Commandes utiles :**

```powershell
git remote -v                  # show configured remotes
git clone https://github.com/USERNAME/REPO-NAME.git   # download an existing repo
```

## Premier exemple de code

**Envoyer le projet `calculator` de la leçon précédente sur GitHub, étape par étape :**

**Étape 1 — un compte.** Allez sur [github.com](https://github.com) → **Sign up**. Un nom d'utilisateur professionnel (il apparaîtra sur votre CV !). Il est recommandé d'utiliser le même e-mail que celui défini dans `git config`.

**Étape 2 — un nouveau Repository.** Sur le site : **+** (en haut) → **New repository** :

- **Repository name :** `calculator`
- **Public** (visible par tous) ou **Private**.
- **Ne cochez pas** « Add a README », « .gitignore » ni « license ». Nous avons déjà un Repository local, et nous voulons commencer avec un Remote **vide**.
- **Create repository**.

**Étape 3 — relier et envoyer.** GitHub affiche les commandes. Depuis le dossier `calculator` :

```powershell
git remote add origin https://github.com/dana-cohen/calculator.git
git branch -M main
git push -u origin main
```

**Sortie :**

```text
Enumerating objects: 18, done.
Counting objects: 100% (18/18), done.
Delta compression using up to 8 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (18/18), 1.92 KiB | 1.92 MiB/s, done.
Total 18 (delta 4), reused 0 (delta 0), pack-reused 0
To https://github.com/dana-cohen/calculator.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
```

**Étape 4 — vérifier.** Actualisez la page du Repository sur GitHub. Les fichiers sont là ! Cliquez sur **Commits** pour voir tout l'historique, avec les messages que vous avez écrits.

## Analyse du code ligne par ligne

| Commande | Explication |
|---|---|
| `git remote add origin <url>` | « Enregistre un Remote nommé `origin`, à cette adresse ». Elle ne fait qu'enregistrer, et n'envoie rien. |
| `git branch -M main` | S'assure que la branche actuelle s'appelle `main`. (Si vous avez défini `init.defaultBranch main`, c'est déjà le cas, et la commande ne fait pas de mal.) |
| `git push -u origin main` | **Envoie** la branche `main` vers `origin`. `-u` (upstream) établit le lien entre elles, pour que désormais `git push` suffise. |
| `Writing objects: 100%` | Les Commits et les fichiers sont envoyés (sous forme compressée) au serveur. |
| `* [new branch] main -> main` | La branche `main` a été créée sur GitHub, avec votre historique. |

## Un autre exemple

**Un cycle de travail complet après la liaison** — une modification, un Commit, un Push, et une vérification sur le site :

```powershell
git status
git add calculator.py
git commit -m "Add power function"
git push
git status
```

Dans `calculator.py` :

```python
def power(base, exponent):
    return base ** exponent
```

**Sortie de `git push` :**

```text
To https://github.com/dana-cohen/calculator.git
   b81c0f4..e2f7a90  main -> main
```

**Sortie de `git status` après le push :**

```text
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
```

**Analyse :**

- `b81c0f4..e2f7a90` — la branche sur GitHub a « avancé » du Commit précédent au nouveau.
- `Your branch is up to date with 'origin/main'` — le local et le Remote sont **synchronisés**. Avant le push, `git status` aurait écrit `Your branch is ahead of 'origin/main' by 1 commit`, c'est-à-dire « vous avez un Commit qui n'a pas encore été envoyé ».
- Sur le site, dans `calculator.py`, on voit la nouvelle fonction, et dans l'historique `Add power function`.

### README.md — la carte de visite du projet

GitHub affiche automatiquement le fichier `README.md` sur la page principale du Repository. Écrivez-en un dans chaque projet :

```text
# Calculator

A simple Python calculator - Kodkod 6 intro course, week 2.

## How to run

    python main.py

## Functions

- add, subtract, multiply, divide, power
```

Le fichier est écrit en **Markdown** : `#` = un titre, `-` = une liste. Ensuite : `git add README.md`, `git commit -m "Add README"`, `git push`.

## Erreur courante

**Erreur 1 : GitHub demande un mot de passe dans le terminal, et le mot de passe « ne fonctionne pas ».**

```text
remote: Support for password authentication was removed on August 13, 2021.
fatal: Authentication failed for 'https://github.com/...'
```

GitHub n'accepte pas le mot de passe du compte dans le terminal. La solution recommandée : Git pour Windows et Mac est fourni avec **Git Credential Manager**, qui ouvre une fenêtre de connexion dans le navigateur. Si elle ne s'ouvre pas, créez un **Personal Access Token** : sur le site → Settings → Developer settings → Personal access tokens. Collez le jeton à la place du mot de passe.

**Erreur 2 : un Remote créé avec un README, et un push refusé.**

```text
! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/...'
hint: Updates were rejected because the remote contains work that you do not have locally.
```

Vous avez coché « Add a README » en créant le Repository sur le site, donc GitHub a un Commit que vous n'avez pas. La solution la plus simple à ce stade : supprimez le Repository sur le site (Settings → Delete) et recréez-le **vide**. (La « vraie » solution est `git pull`, que nous n'avons pas encore étudié en profondeur.)

**Erreur 3 : `remote origin already exists`.**

```text
error: remote origin already exists.
```

Vous avez déjà ajouté un Remote avec ce nom (peut-être avec une mauvaise adresse). Vérifiez avec `git remote -v`, et corrigez : `git remote set-url origin <correct-url>`.

**Erreur 4 : envoyer des secrets.** Un fichier avec un mot de passe ou une clé d'API envoyé vers un Repository **public** est considéré comme **divulgué**, même si vous le supprimez dans le Commit suivant, car il reste dans l'historique. Des robots parcourent GitHub et trouvent les clés en quelques minutes. **`.gitignore` avant le premier Commit**, et jamais de secrets dans le code.

**Erreur 5 : un Commit sans Push.** « J'ai fait un Commit, donc c'est sur GitHub ». Non ! Un Commit est seulement local, et seul `push` envoie.

<!-- 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: Se connecter à GitHub

Vous avez créé un Repository vide sur GitHub à l'adresse `https://github.com/dana-cohen/calculator.git`. L'ordinateur a déjà un Repository local avec des Commits. Écrivez les commandes qui le relient à GitHub et envoient le code pour la première fois.

{{< solution >}}
```powershell
git remote add origin https://github.com/dana-cohen/calculator.git
git branch -M main
git push -u origin main
```

- `git remote add origin ...` — définit le Repository sur GitHub comme un **Remote** nommé `origin`.
- `git branch -M main` — nomme la branche principale `main`.
- `git push -u origin main` — envoie les Commits. `-u` mémorise la liaison, et la fois suivante `git push` suffit.
{{< /solution >}}

### Exercice 2: Local face à Remote

Dana a fait trois Commits sur son ordinateur, mais n'a pas lancé `git push`. Un ami ouvre le Repository sur GitHub.

1. Voit-il les trois Commits ?
2. L'ordinateur de Dana a cassé avant qu'elle ne lance le push. Qu'est-ce qui a été perdu ?

{{< solution >}}
1. **Non.** Un Commit n'est enregistré que dans le Repository **local**. GitHub n'est mis à jour qu'après `git push`.
2. Les trois Commits **ont été perdus** — ils n'étaient que sur l'ordinateur. C'est exactement la raison d'être du push : une **sauvegarde** en dehors de l'ordinateur, et le partage avec les autres.
{{< /solution >}}

### Exercice 3: push, clone et remote

Associez chaque commande à ce qu'elle fait :

```text
git push
git clone <url>
git remote add origin <url>
```

(a) Télécharge un Repository existant de GitHub sur un nouvel ordinateur. (b) Définit où envoyer. (c) Envoie des Commits vers GitHub.

{{< solution >}}
| Commande | Ce qu'elle fait |
|---|---|
| `git push` | (c) — envoie les Commits locaux vers le Remote |
| `git clone <url>` | (a) — télécharge une copie complète d'un Repository, avec tout l'historique |
| `git remote add origin <url>` | (b) — définit le Remote, une fois par Repository |
{{< /solution >}}

### Exercice 4: De bons messages de Commit

Pour chaque message — bon ou non ? Sinon, écrivez une bonne version.

```text
1. fix
2. Add divide function to calculator
3. changes
4. asdf
5. Fix crash when dividing by zero
```

{{< solution >}}
| Message | Bon ? | Une bonne version |
|---|---|---|
| `fix` | Non — il ne dit pas ce qui a été corrigé | `Fix rounding in VAT calculation` |
| `Add divide function to calculator` | **Oui** | — |
| `changes` | Non — chaque Commit est « des changements » | `Update README with run instructions` |
| `asdf` | Non — sans signification | `Add input validation for age` |
| `Fix crash when dividing by zero` | **Oui** | — |

Un bon message : **une phrase courte, à l'impératif, qui décrit ce que fait la modification**.
{{< /solution >}}

### Exercice 5: La routine quotidienne

Vous avez ajouté une fonction `power` au projet. Remettez les commandes dans le bon ordre :

```text
git push
git commit -m "Add power function"
git status
git add calculator.py
```

{{< solution >}}
```powershell
git status
git add calculator.py
git commit -m "Add power function"
git push
```

1. `git status` — voir ce qui a changé.
2. `git add` — choisir ce qui entre.
3. `git commit` — enregistrer un instantané local.
4. `git push` — envoyer sur GitHub.

C'est le cycle de chaque journée de travail.
{{< /solution >}}

<!-- exercises:end -->

## Résumé

- **GitHub** = un serveur qui héberge des Repositories dans le cloud. Le Git local communique avec lui en HTTPS.
- **Remote** = une copie distante. **origin** = le surnom en usage pour le principal.
- Première liaison : `git remote add origin <url>` → `git push -u origin main`. Ensuite : `git push`.
- **Commit = local. Push = vers le cloud.** `git status` indique si vous êtes « en avance » sur le Remote.
- Un message de Commit : impératif, précis, court, une seule modification, en anglais. « If applied, this commit will ___ ».
- Les secrets ne sont jamais envoyés. `.gitignore` avant le premier Commit.

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

## Documentation officielle

- [GitHub Docs — Creating an account](https://docs.github.com/en/get-started/start-your-journey/creating-an-account-on-github)
- [Pro Git — Working with Remotes](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes)
- [git push](https://git-scm.com/docs/git-push)
- [GitHub Docs — About READMEs](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes)

<!-- docs:end -->
