---
lang: fr-fr
---
# Formation GIT
 
GIT est un logiciel de gestion collaborative de versions de code, utilisant des principes de théorie des graphes.
Ça paraît compliqué dit comme ça. En plus simple:
* Vous avez une timeline avec des points de sauvegarde (des commits)
* Vous pouvez créer des "branches", développer des choses dessus, les "merge" dans la branche initiale...
Aujourd'hui on va apprendre à manier GIT et ses nombreuses commandes.
```mermaid
gitGraph
commit id: "Initial commit"
commit id: "Create main.c"
branch feature
commit id: "Add feature"
checkout main
commit id: "Small fix"
checkout feature
commit id: "Bugfix on feature"
checkout main
commit id: " "
checkout feature
branch smallfix
commit id: "another fix"
checkout feature
merge smallfix
commit id: "and so on"
```
## Petit setup
* Sous WSL ou Ubuntu, l'exécutable `git` est normalement déjà installé. Dans le cas contraire, faites `sudo apt install git`.
* Sous Windows, vous pouvez installer *Git for Windows* en suivant les instructions sur [cette page](https://git-scm.com/download/win). En revanche, les commandes de cette formation seront sous format UNIX (Linux, WSL, MacOS). Si vous n'êtes pas à l'aise avec l'invite de commande Windows, je vous recommande d'utiliser WSL.
Connectez vous sur le [GitLab de DaTA](https://gitlab.data-ensta.fr), puis demandez à être ajoutés sur le groupe Formation, qui vous permettra d'accéder à [ce repository](https://gitlab.data-ensta.fr/formation-2022/formation-git).
### Création de clé SSH
On va tout d'abord créer une clé SSH pour pouvoir interagir avec les projets du GitLab DaTA.
1. Vérifions si une clé SSH existe déjà :
Faites `ls ~/.ssh` et regardez ce qui s'affiche. Si un fichier du style `id_ed25519.pub` est affiché, faites `cat id_ed25519.pub`. Bravo, vous avez déjà une clé SSH. Passez directement à l'étape 4.
2. Dans le cas contraire, exécutez la commande `ssh-keygen -t ed25519`, ou éventuellement `ssh-keygen -t ed25519 -C votre.adresse@email.fr` pour identifier votre clé avec votre adresse mail.
Normalement, il s'affiche alors quelque chose comme :
```
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```
Appuyez sur entrée pour continuer en gardant le nom de fichier par défaut.
3. Ensuite s'affiche:
```
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```
Appuyez sur entrée les deux fois, sauf si vous voulez encrypter votre clé avec un mot de passe.
4. A présent, copiez le contenu du fichier `id_ed25519.pub`:
```bash
cat ~/.ssh/id_ed25519.pub
```
5. Connectez vous sur le GitLab de DaTA et dans vos préférences, sélectionnez "Clés SSH". Dans l'interface, collez le contenu de `id_ed25519.pub`, donnez un nom à votre clé pour vous rappeler sur quel appareil elle est, et enfin cliquez sur "Ajouter la clé".

### Cloner un repository
Ouvrez le [repository de formation](https://gitlab.data-ensta.fr/formation-2022/formation-git). Identifiez le bouton `Clone`:

Cliquez dessus et copiez le champ "Clone with SSH":

Dans un dossier de votre choix, exécutez à présent la commande suivante avec l'adresse SSH du repository que vous venez de copier:
```bash
git clone <adresse>
```
Un dossier formation-git est alors créé. Ouvrez VSCode dedans avec `code formation-git` ou bien tout autre éditeur de code que vous préférez.
### Branch out
En arrivant dans le repository, vous êtes par défaut dans la branche `main`. Mais on n'a pas trop envie que vous fassiez des bêtises dessus.
Vous allez devoir créer votre propre branche. C'est sur celle-ci que vous serez libre de vous amuser ! 😀
Créez une branche avec votre nom et votre prénom:
```bash
git branch nom-prenom
```
N'oubliez pas de vous y rendre 😉
```bash
git switch nom-prenom
```
Il faut maintenant push votre branch, pour l'ajouter au repo :
```bash
git push --set-upstream origin <nom de la branche>
```
Le repo ressemble à présent à ça:
```mermaid
gitGraph
commit id: "Etat cloné"
branch votre-nom
checkout votre-nom
commit id: "Sur la branche"
```
::: success
Votre branche est bien créée, mais elle est vide ! On va tout de suite s'affairer à la remplir.
:::
### Commit (crimes)
Le commit est un checkpoint, il fixe un état du projet à un instant donné.
Dès que vous effectuez une modification sur votre projet, vous avez la possibilité de créer un commit associé à cette modification. Après ça, vous aurez le pouvoir de naviguer entre les différents commits, comme un voyageur dans le temps. 🕜
Si vous estimez que vos modifications sont assez importantes pour être conservées, alors il est temps de les inscrire dans un commit ! 🥳
:::info
A tout moment, vous pouvez taper la commande `git status` pour connaître quels sont les fichiers que vous avez modifiés ou encore la branche sur laquelle vous vous trouv.
`git diff` vous permet de voir la différence, ligne par ligne du fichier modifié par rapport au fichier initial
:::
On va donc faire une modification dans la branche.
Créez une fonction C `void communistGreeting(char * name)`:
```clike=3
void communistGreeting(char * name) {
printf("\x1B[31;1mHello, %s!\x1B[0m\n", name);
}
```
On va construire notre premier commit🥳: il est composé d'une liste de modifications à sauvegarder. On ajoute un fichier à cette liste avec `git add`:
```bash
git add main.c
```
Et on finalise le commit avec, vous l'aurez compris, `git commit`:
```bash
git commit -m "un message de commit"
```
Le message est ce qui sera sauvegardé dans l'historique: il explique en quelques mots ce que le commit apporte comme modifications. Par exemple:
* `"ajout de la fonction communistGreeting"`
* `"fix function doSomething()"`
* `"robinetterie"`
* `"small fix"`
::: info
Si vous avez une erreur lors de votre tout premier commit, exécutez les commandes suivantes avec votre email (mail ENSTA, pour le GitLab de DaTA) et votre nom:
```bash
git config --global user.email "votre.email@ensta-paris.fr"
git config --global user.name "Votre Nom"
```
:::
### Push toi de là
Il faut maintenant que vous publiez vos modifs, afin que le monde ENTIER soit au courant ! 🥳
Pour le moment, deux versions du projet existent:
* votre version locale, avec vos modifications
* la version sur GitLab, qui est une version distante servant à partager l'historique entre les différents collaborateurs
Mais pour que Git soit vraiment utile, il faut pouvoir synchroniser les différentes versions. C'est là qu'intervient la commande `git push`: elle vous permet d'envoyer les modifications locales sur la version du serveur GitLab.
::: success
Bravo, vous avez push votre premier commit sur le GitLab de DaTA 🥳
Si vous voulez, amusez vous à faire quelques autres modifications pour vous habituer à l'utilisation de ces commandes.
:::
### L'union fait la force
Maintenant, il est temps pour vous de vous mettre par binôme !
Les deux membres doivent se placer sur la branche de son meilleur pote (aka son binôme) pour la formation. On se rapelle de la commande `git switch <nom de branche>`.
::: danger
Oups ! Il y'a une petite erreur qui a pu apparaître ! (C'était bien tenté pourtant)
:::
En effet, votre repo local n'est pas au courant des dernières modifications du repo à distance. Pour cela, il faut recupérer les dernières modifications.
Un peu d'anglais, l'antonyme de `push`, c'est ... `pull` ! Si la commande `git push` envoie les modifications de la copie locale sur la copie distante, la commande `git pull` fait exactement le contraire et synchronise votre version avec celle du serveur.
Après ça, vous pourrez enfin aller sur la branche de votre compagnon d'aventure.
### Collaboration (comme en 40)
Créez chacun un fichier `.txt` avec votre nom dans la branche de l'autre, et remplissez y du texte.
Comme les modifications sont séparées dans deux fichiers indépendants, la synchronisation entre les branches est aisée. Créez chacun un commit avec votre fichier texte, et faites un `git push`, puis revenez dans votre branche, et récupérez les modifications de votre propre branche.
::: success
Vous avez collaboré sur la branche de quelqu'un d'autre ! Même si l'exemple est un peu simplet, c'est sur ces bases qu'on peut orchestrer tout un projet à plusieurs.
:::
### Rebase and merge
Mais quel intérêt de collaborer sur des historiques séparés si on ne peut pas réunir les différentes features en un seul programme ?
C'est là qu'intervient la commande `git merge`, qui permet de fusionner deux branches. Apprenons à l'utiliser !
Tirez à pile ou face pour décider d'un membre du binôme qui va aller sur la branche de l'autre, et créér à partir de celle la une *troisième* branche: (ne l'appelez pas troisème branche, trouvez un nom unique)
```mermaid
gitGraph
commit id: "Etat initial"
branch binome-A
commit id: " "
checkout main
branch binome-B
commit id: " "
checkout binome-A
commit id: "blabla"
checkout binome-B
branch troisieme-branche
commit id: "Nouvelle feature"
checkout binome-B
commit id: "Commit embêtant"
```
::: info
**Rappel:** on a vu comment créer et push une branche dans la section "Branch out" plus haut
:::
Suivez le tableau suivant en parallèle, modifiant le même fichier (`main.c`, par exemple) :
| Binôme A | Binôme B |
|:------------------------:|:-------------------------:|
| Crée branche 3 | Reste sur branche B |
| Crée un commit "feature" | Crée un commit "embêtant" |
| Push son commit | Push son commit |
On obtient un repo qui ressemble à celui schématisé plus haut.
Mais cette fois, on ne peut pas juste ajouter des fichiers séparés pour fusionner les historiques ! Le même fichier existe en deux version différentes. On va donc devoir faire un `rebase`, pour régler les conflits.
| Avant | Après |
|-------|-------|
| | |
L'objectif du rebase est de linéariser l'historique pour faire fusionner les branches facilement.
La commande magique, en étant sur la branche à rebase:
```bash
git pull --rebase origin <autre branche>
```
Avec les noms dans les schémas, cela donne:
```bash
git switch troisieme-branche
git pull --rebase origin binome-B
```
::: info
Vous pouvez inspecter les commits effectués sur le repo à l'aide de la commande `git log`. On voit que l'historique est modifié.
:::
Enfin, on peut se placer sur la branche `binome-B` et merge la branche `troisieme-branche`, avec la commande:
```bash
git switch binome-B
git merge troisieme-branche
```
```mermaid
gitGraph
commit id: "Etat initial"
branch binome-A
commit id: " "
checkout main
branch binome-B
commit id: " "
checkout binome-A
commit id: "blabla"
checkout binome-B
commit id: "Commit embêtant"
branch troisieme-branche
commit id: "Nouvelle feature"
checkout binome-B
merge troisieme-branche
```
*[commit]: Point de sauvegarde de l'état de votre code
*[repository]: Projet GIT réunissant vos fichiers de code et l'historique des modifications
*[branche]: Historique parallèle de code, pouvant être réuni en un seul historique au moyen d'un merge