---
# System prepended metadata

title: Formation GIT

---

---
lang: fr-fr
---

# Formation GIT

![](https://i.imgur.com/Rgf5vGR.png =100x) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ![](https://www.colinodell.com/sites/default/files/styles/responsive/public/2018-03/Git-Logo-2Color.png =200x)

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é".
  
  ![](https://i.imgur.com/8Sz0fe5.png)

### Cloner un repository

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

![](https://i.imgur.com/auhARH3.png =100x)

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

![](https://i.imgur.com/z7Uf3vu.png =300x)


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 |
|-------|-------|
|![](https://i.imgur.com/FdpElfv.png =350x)   |![](https://i.imgur.com/Y9LoRLS.png =350x) |

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