A02

Git — Les bases

Shell

Introduction

Git est un système de contrôle de version. En termes simples, il garde un historique complet de chaque modification que tu fais dans ton code. Chaque fois que tu "sauvegardes" (on dit commit), git prend une photo de l'état de tous tes fichiers à cet instant. Tu peux revenir à n'importe quelle photo à tout moment.

Pourquoi c'est indispensable :

  • Sécurité : ton code est sauvegardé sur un serveur distant. Si ton disque dur crame, si tu fais un rm -rf de travers, ton code est en sécurité.
  • Historique : tu peux voir exactement ce que tu as modifié, quand, et pourquoi. Si une modification casse quelque chose, tu reviens en arrière.
  • Collaboration : plusieurs personnes peuvent travailler sur le même projet en parallèle. Git gère la fusion des modifications.
  • Traçabilité : à 42, la Moulinette vérifie que ton code est bien pushé sur le Vogsphere. Pas de push, pas de correction. Git est obligatoire.

Git a été créé en 2005 par Linus Torvalds (le créateur de Linux) parce qu'il avait besoin d'un outil rapide et fiable pour gérer le code du noyau Linux, qui a des millions de lignes et des milliers de contributeurs.

Git est distribué

La plupart des gens imaginent un système centralisé : un serveur unique qui stocke le code, et tout le monde s'y connecte. Git ne fonctionne pas comme ça.

Avec git, chaque personne a une copie complète du projet, incluant tout l'historique. Tu peux travailler, commiter, créer des branches, revenir en arrière — tout ça sans connexion internet, en local sur ta machine.

Le serveur distant (GitHub, GitLab, Vogsphere de 42) n'est qu'un point de synchronisation. Tu y envoies tes modifications quand tu es prêt, et tu récupères celles des autres. Mais le serveur n'est pas indispensable pour travailler — il est indispensable pour partager.

┌──────────────┐     git push     ┌──────────────┐
│  Ton ordi    │ ───────────────> │   Serveur    │
│  (local)     │                  │   (remote)   │
│              │ <─────────────── │              │
│  copie       │     git pull     │  copie       │
│  complète    │                  │  complète    │
└──────────────┘                  └──────────────┘

Les trois zones de git

Git organise ton travail en trois zones. Comprendre ces trois zones c'est comprendre git :

Working directory  ──git add──>  Staging area  ──git commit──>  Repository
   (tes fichiers)                  (index)                     (historique)
       │                              │                            │
   Tu édites ici             Tu choisis ici              Les commits vivent ici

Ce système en trois étapes peut paraître compliqué au début, mais il te donne un contrôle total. Tu peux modifier 10 fichiers, mais n'en commiter que 3. Tu peux vérifier exactement ce qui va être commité avant de le faire.

Configurer git

Identité

Avant de pouvoir commiter, git a besoin de savoir qui tu es. Chaque commit porte un nom et un email — c'est ce qui apparaît dans l'historique.

Terminal
git config --global user.name "isoulima"
git config --global user.email "isoulima@student.42lausanne.ch"

Un flag (ou option) c'est un paramètre qui commence par - ou -- et qui modifie le comportement d'une commande. Le flag --global applique la configuration à tout ton système (tous tes projets). Sans --global, la configuration ne s'applique qu'au projet courant.

Pour vérifier :

Terminal
git config --list
user.name=isoulima
user.email=isoulima@student.42lausanne.ch

Éditeur par défaut

Certaines commandes git ouvrent un éditeur de texte (pour écrire un message de commit, par exemple). Par défaut c'est souvent vim. Si tu préfères nano :

Terminal
git config --global core.editor "nano"

Où est stockée la config ?

  • --global~/.gitconfig
  • Sans flag → .git/config dans le projet
Terminal
cat ~/.gitconfig
[user]
name = isoulima
email = isoulima@student.42lausanne.ch

Créer un dépôt

Deux façons de démarrer :

git init — Créer un nouveau dépôt

Terminal
mkdir mon_projet
cd mon_projet
git init
Initialized empty Git repository in /home/isoulima/mon_projet/.git/
Terminal
ls -la .git/
total 32
drwxr-xr-x 7 isoulima 42staff 4096 Apr 5 10:00 .
drwxr-xr-x 3 isoulima 42staff 4096 Apr 5 10:00 ..
-rw-r--r-- 1 isoulima 42staff 23 Apr 5 10:00 HEAD
drwxr-xr-x 2 isoulima 42staff 4096 Apr 5 10:00 branches
-rw-r--r-- 1 isoulima 42staff 92 Apr 5 10:00 config
drwxr-xr-x 2 isoulima 42staff 4096 Apr 5 10:00 hooks
drwxr-xr-x 2 isoulima 42staff 4096 Apr 5 10:00 objects
drwxr-xr-x 4 isoulima 42staff 4096 Apr 5 10:00 refs

git clone — Copier un dépôt existant

Terminal
git clone git@vogsphere.42lausanne.ch:vogsphere/intra-uuid-abc123
Cloning into 'intra-uuid-abc123'...

La différence entre clone et simplement copier un dossier : clone établit automatiquement la connexion avec le serveur distant (le "remote"). Tu pourras faire git push et git pull sans configuration supplémentaire.

Terminal
cd intra-uuid-abc123
git remote -v
origin git@vogsphere.42lausanne.ch:vogsphere/intra-uuid-abc123 (fetch)
origin git@vogsphere.42lausanne.ch:vogsphere/intra-uuid-abc123 (push)

Le cycle de base : status, add, commit, push

C'est le workflow que tu vas répéter des centaines de fois :

1. Tu modifies tes fichiers
2. git status      → tu vérifies ce qui a changé
3. git add         → tu prépares les fichiers à commiter
4. git commit      → tu crées un snapshot
5. git push        → tu envoies au serveur

git status — Où en suis-je ?

Terminal
touch main.c Makefile
git status
On branch master
 
No commits yet
 
Untracked files:
(use "git add <file>..." to include in what will be committed)
 
main.c
Makefile
 
nothing added to commit but untracked files present

Après avoir modifié un fichier suivi :

Terminal
git status
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
 
modified: main.c

Après git add :

Terminal
git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
 
new file: main.c
new file: Makefile

Après git commit :

Terminal
git status
On branch master
nothing to commit, working tree clean

Prends l'habitude de faire git status avant chaque add et avant chaque commit. C'est ton GPS.

git add — Préparer les fichiers

Terminal
git add main.c
Terminal
git add main.c Makefile ft_putchar.c
Terminal
git add .

Le . signifie "tout dans le dossier courant et ses sous-dossiers". C'est pratique mais dangereux — tu peux ajouter des fichiers que tu ne voulais pas (fichiers compilés, fichiers temporaires). Toujours faire git status avant pour vérifier.

Terminal
git restore --staged main.c

Le fichier reste modifié, mais n'est plus staged.

git commit — Créer un snapshot

Terminal
git commit -m "add ft_putchar function"
[master 1a2b3c4] add ft_putchar function
1 file changed, 7 insertions(+)
create mode 100644 ft_putchar.c

Le flag -m permet d'écrire le message directement. Sans -m, git ouvre un éditeur de texte pour que tu écrives le message.

  • Décrit ce que tu as fait, pas ce que tu vas faire
  • Est court et précis (une ligne, 50 caractères max idéalement)
  • Commence par un verbe d'action : "add", "fix", "update", "remove"

Bons messages :

add ft_putchar function
fix segfault in ft_split with empty string
update Makefile to include bonus rule
remove unused variable in ft_strlen

Mauvais messages :

update            ← trop vague, update quoi ?
fix               ← fix quoi ?
wip               ← personne ne saura ce que tu faisais
asdfgh            ← sérieusement
j'ai fini         ← fini quoi ?

git push — Envoyer au serveur

Terminal
git push origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Writing objects: 100% (3/3), 312 bytes | 312.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To vogsphere.42lausanne.ch:vogsphere/intra-uuid-abc123
m0n1o2p..1a2b3c4 master -> master

Après le push, ton code est en sécurité sur le serveur. Les autres (et la Moulinette) peuvent y accéder.

Terminal
git push origin master
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs
hint: Updates were rejected because the remote contains work that you do not have locally.

Ça veut dire que le serveur a des commits que tu n'as pas. Il faut d'abord faire git pull pour récupérer les changements, puis repusher.

git pull — Récupérer du serveur

Terminal
git pull origin master
  1. Télécharge les nouveaux commits du serveur
  2. Fusionne les changements du serveur avec les tiens

Si tu travailles seul, ça se passe automatiquement sans conflit. En équipe, c'est différent — mais les branches et la gestion de conflits sont des sujets plus avancés.

Voir l'historique

git log — L'historique des commits

Terminal
git log
commit 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b (HEAD -> master)
Author: isoulima <isoulima@student.42lausanne.ch>
Date: Sat Apr 5 10:30:00 2026 +0200
 
add ft_putchar function
 
commit m0n1o2pd5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
Author: isoulima <isoulima@student.42lausanne.ch>
Date: Sat Apr 5 10:00:00 2026 +0200
 
initial commit

Chaque commit affiche :

  • L'identifiant unique : une longue suite de lettres et chiffres (40 caractères). C'est le numéro de série du commit — aucun autre commit n'aura le même.
  • HEAD -> master : indique que c'est le commit le plus récent de la branche master.
  • L'auteur et la date.
  • Le message.
Terminal
git log --oneline
1a2b3c4 add ft_putchar function
m0n1o2p initial commit

Un commit par ligne, avec le hash court (7 caractères) et le message.

Terminal
git log -p
Terminal
git log -5 # Les 5 derniers
git log --oneline -10

git diff — Voir les modifications

Terminal
git diff
diff --git a/ft_putchar.c b/ft_putchar.c
--- a/ft_putchar.c
+++ b/ft_putchar.c
@@ -1,5 +1,7 @@
#include <unistd.h>
 
+#include "libft.h"
+
void ft_putchar(char c)
{
write(1, &c, 1);

Les lignes avec + sont ajoutées (en vert dans le terminal). Les lignes avec - sont supprimées (en rouge). Les lignes sans signe sont le contexte.

Terminal
git diff --staged
Terminal
git diff m0n1o2p 1a2b3c4

Ignorer des fichiers — .gitignore

Certains fichiers ne doivent jamais être versionnés :

  • Les fichiers compilés (.o, .a, a.out) — ils sont regénérés à chaque compilation
  • Les fichiers temporaires de l'éditeur (.swp, ~)
  • Les fichiers spécifiques à l'OS (.DS_Store sur macOS)
  • Les fichiers contenant des secrets (clés API, mots de passe)

Le fichier .gitignore à la racine du projet liste les patterns à ignorer :

Terminal
cat .gitignore
# Fichiers compilés
*.o
*.a
a.out
 
# Fichiers temporaires
*~
*.swp
.DS_Store
 
# Dossiers
.vscode/

Une fois dans le .gitignore, les fichiers n'apparaissent plus dans git status et ne sont plus ajoutés par git add ..

Terminal
git rm --cached fichier.o
git commit -m "remove tracked .o file"

.gitignore typique à 42

# Compiled files
*.o
*.a
*.so
*.dylib
a.out

# Editor files
*~
*.swp
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Debug
*.dSYM/

Mets ce .gitignore dans chaque projet dès le premier commit. C'est une bonne habitude.

La clé SSH

Pourquoi SSH ?

Pour communiquer avec un serveur git (GitHub, Vogsphere), il faut prouver ton identité. Deux options :

  • HTTPS : tu donnes ton login + mot de passe à chaque push. Pratique mais pénible.
  • SSH : tu configures une paire de clés une fois, et ensuite l'authentification est automatique.

À 42 on utilise SSH.

Comment ça marche

SSH utilise un système de deux clés liées : une clé privée (que tu gardes secrète) et une clé publique (que tu donnes au serveur). C'est comme une boîte aux lettres : tout le monde peut y déposer du courrier (clé publique = la fente), mais seul toi peut l'ouvrir (clé privée = la clé de la boîte). Le serveur vérifie que tu es bien le propriétaire de la clé publique en te posant une question que seul quelqu'un avec la clé privée peut résoudre.

  • La clé privée reste sur ta machine, dans ~/.ssh/. Ne la partage jamais. C'est l'équivalent de ton mot de passe.
  • La clé publique est donnée au serveur (GitHub, Vogsphere). Elle permet au serveur de vérifier que c'est bien toi.

Générer une clé SSH

Terminal
ssh-keygen -t ed25519 -C "isoulima@student.42lausanne.ch"
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/isoulima/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/isoulima/.ssh/id_ed25519
Your public key has been saved in /home/isoulima/.ssh/id_ed25519.pub
  • -t ed25519 : ed25519 c'est le type de clé recommandé. C'est le plus récent et le plus sûr. Si ça ne marche pas sur ton système, utilise -t rsa -b 4096 à la place.
  • -C : un commentaire pour identifier la clé (convention : ton email).
  • Passphrase : un mot de passe qui protège ta clé privée. Tu peux laisser vide pour plus de confort, mais c'est moins sûr.

Deux fichiers sont créés :

  • ~/.ssh/id_ed25519 — la clé privée (ne la partage JAMAIS)
  • ~/.ssh/id_ed25519.pub — la clé publique (c'est celle-ci que tu donnes)

Ajouter la clé au serveur

Terminal
cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHx7... isoulima@student.42lausanne.ch

Copie tout (de ssh-ed25519 à la fin).

Terminal
ssh -T git@github.com
Hi isoulima! You've successfully authenticated, but GitHub does not provide shell access.

Ce message veut dire que ça marche. Le "does not provide shell access" est normal — GitHub n'est pas un serveur shell, c'est un serveur git.

Permissions de la clé

La clé privée doit avoir les permissions 600 (toi seul peut la lire). Sinon SSH refuse de l'utiliser :

Terminal
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Si tu vois l'erreur "UNPROTECTED PRIVATE KEY FILE", c'est que les permissions sont trop ouvertes.

ssh-agent — Éviter de retaper la passphrase

Si tu as mis une passphrase sur ta clé, SSH te la demande à chaque utilisation. Pour l'éviter :

Terminal
eval "$(ssh-agent -s)"
Agent pid 12345
ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/isoulima/.ssh/id_ed25519:
Identity added: /home/isoulima/.ssh/id_ed25519

L'agent SSH retient ta passphrase jusqu'à la fermeture du terminal.

Annuler des erreurs

Annuler les modifications d'un fichier (avant add)

Terminal
git restore main.c

Le fichier revient à son état du dernier commit. Attention : les modifications non commitées sont perdues définitivement.

Annuler un add (unstage)

Terminal
git restore --staged main.c

Le fichier sort de la staging area mais tes modifications sont conservées.

Modifier le dernier commit

Tu as oublié un fichier, ou tu veux corriger le message :

Terminal
git add fichier_oublie.c
git commit --amend -m "add ft_putchar with header"

Revenir à un commit précédent (pour voir)

Terminal
git checkout a1b2c3d

Tu es en mode "détaché" (detached HEAD). Tu peux regarder le code à ce point de l'historique. Pour revenir au présent :

Terminal
git checkout master

git reset — Revenir en arrière (avec ou sans perte)

Terminal
git reset --soft HEAD~1 # Annule le dernier commit, garde les fichiers staged
git reset --mixed HEAD~1 # Annule le dernier commit, garde les fichiers modifiés
git reset --hard HEAD~1 # Annule le dernier commit, SUPPRIME les modifications

Commandes utiles

git show — Voir le contenu d'un commit

Terminal
git show 1a2b3c4

Affiche le message et les modifications du commit.

git blame — Qui a écrit cette ligne ?

Terminal
git blame main.c
1a2b3c4d (isoulima 2026-04-05 10:30:00 +0200 1) #include <unistd.h>
1a2b3c4d (isoulima 2026-04-05 10:30:00 +0200 2)
m0n1o2pd (isoulima 2026-04-05 10:00:00 +0200 3) int main(void)

Pour chaque ligne : quel commit l'a introduite, par qui, et quand. Utile pour comprendre l'historique d'un fichier.

git stash — Mettre de côté temporairement

Tu as des modifications en cours mais tu dois changer de contexte (un hotfix, un autre exercice) :

Terminal
git stash # Met de côté les modifications
git stash list # Voir les stash
git stash pop # Récupérer les modifications

C'est comme une pile de brouillons.

Bonnes pratiques

Le cycle quotidien

Le workflow git que tu vas répéter tous les jours :

  1. Coder / modifier tes fichiers
  2. git status pour vérifier ce qui a changé
  3. git add pour préparer les fichiers
  4. git commit -m "message clair" pour sauvegarder
  5. git push pour envoyer au serveur

Commite souvent, en petits incréments logiques. Un commit par fonctionnalité ou par correction. Pas un gros commit avec 10 changements différents.

Avant de rendre un projet

Checklist :

  1. git status — tout est commité ? Rien en rouge ?
  2. git log — le dernier commit a le bon contenu ?
  3. git push — tout est pushé ?
  4. Vérifie sur l'interface web que le bon commit est visible
  5. Lis le sujet une dernière fois pour vérifier que tu n'as rien oublié

Questionnaire

Vérifie tes acquis — sélectionne la bonne réponse pour chaque question

1Quelle est la différence entre git add et git commit ?
2Tu fais git status et tu vois un fichier en rouge sous "Changes not staged for commit". Que signifie cela ?
3Tu as déjà commité un fichier a.out et tu l'ajoutes maintenant au .gitignore. Que se passe-t-il ?
4Quelle commande annule un git add (retire un fichier de la staging area) sans perdre les modifications ?
5Tu viens de faire un commit et tu réalises que tu as oublié d'ajouter un fichier. Que fais-tu ?
6Que contient le dossier .git/ ?
7Tu fais git push et tu obtiens l'erreur "rejected (non-fast-forward)". Pourquoi ?
8Quelle est la différence entre git clone et git init ?
9Tu veux voir uniquement les fichiers que tu as modifiés, pas les détails des modifications. Quelle commande ?
10Pourquoi la clé privée SSH (~/.ssh/id_ed25519) doit avoir les permissions 600 ?