Git

Outil de collaboration

Louvain-li-Nux

Cette présentation est

  • Sous license libre GPLv2.
  • Disponible en ligne : https://git.louvainlinux.org
  • N'hésitez pas à suivre les slides en même temps que la présentation !

Table des matières

  1. Qu'est-ce que git ?
  2. Mise en place de l'environnement
  3. La ligne de commande (CLI)
  4. Concepts de base de git
  5. Les dépôts (et le stage)
  6. Les branches

Git, c'est quoi ?

  • Un système de gestion de versions distribué.
  • VCS (Version Control System), en anglais.

Mise en place de l'environnement

Ouvrez votre émulateur de terminal ("Terminal" sur Windows), et ensuite :

Linux (CtrlShiftC, CtrlShiftV)

$ sudo apt update && sudo apt install git

Windows (CtrlShiftC, CtrlShiftV)

Installez Git depuis votre navigateur. Suivez les recommandations lors de l'installation. Vous devriez avoir une application nommée "Git Bash".

Mac (C, V)

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && brew install git

La ligne de commande (CLI)

Des implémentations GUI existent, mais :

  • Moins flexibles.
  • Opaques.
  • Souvent fermées.
  • Si vous comprenez bien le CLI, vous comprendrez mieux le GUI.

Donc petit détour par les bases du CLI !

La Commande

$ echo "Hello world"  # commande + argument
Hello world           # sortie

Le Chemin (aka Path)

Lorsque vous utilisez un terminal, vous vous trouvez toujours dans un certain dossier de votre ordinateur.
Si vous exécutez la commande

$ pwd #print working directory
/home/theo/

Vous saurez directement où vous vous trouvez !

Le Chemin (aka Path)

Un chemin est comme un fil d'ariane, sous la forme /dossier1/dossier2/dossier3/fichier.txt.

Lorsque le chemin commence par un / cela signifie qu'il est absolu. Autrement dit, c'est un chemin complet depuis la "racine" de votre
disque dur jusqu'a votre position.

Exemple: /home/theo/atelier/cool.txt

Les chemins relatifs

Il est aussi possible de définir un chemin relatif a votre position actuelle.

$ pwd # "print working directory" ou "écrire le dossier de travail"
/home/theo

Ici par exemple, on se trouve dans /home/theo.

Le chemin relatif atelier/fichier.txt représente en fait /home/theo/atelier/fichier.txt

REMARQUE: Il est courant de voir la notation ./atelier/fichier.txt qui indique aussi un chemin relatif, puisque . représente le dossier actuel.

ls (pour LiSt)

On peut lister tous les fichiers/dossiers dans notre dossier de travail :

$ ls
tux	super/

Ou dans un autre dossier :

$ ls super
tux2

cd (Change Directory)

On peut changer notre dossier de travail :

$ pwd
/home/theo
$ cd super
$ pwd
/home/theo/super

Et puis encore :

$ ls
tux2

cd

On peut remonter d'un dossier dans l'arborescence :

$ pwd
/home/theo/super
$ cd ..
$ pwd
/home/theo

Recap

  • pwd : Obtenir le dossier de travail.
  • ls : Afficher le contenu d'un dossier.
  • cd : Changer le dossier de travail.

Concepts de base de git

Les commits

  • Contiennent une ou plusieurs modification·s de fichiers.
  • Sont ordonnés

Une modification de fichier (diff) ?

5- Hello, World
5+ Hello, Git !

Ceci représente la modification du mot World en Git !

Chaque commit contient un ensemble de modifications comme celle-ci.

Organisations des commits

0

Commençons simplement avec un seul commit.

Organisations des commits

0
1

Si on crée un deuxième commit, il sera placé juste après le premier commit.
Les commits sont organisés. Ils se mettent les uns à la suite des autres.

Organisations des commits

0
1
2
3

En travaillant, vous allez construire une suite de commits (appelée arbre), contenant toutes les modifications apportées à vos fichiers.

Je modifie → Je commit → Je modifie → Je commit

Organisations des commits

0
1
2
3

Avant le commit initial, tous les fichiers sont vides.

Organisations des commits

0
1
2
3

Avant le commit initial, tous les fichiers sont vides.

Le HEAD représente l'endroit ou vous vous trouvez actuellement dans l'historique. Le contenu des fichiers que vous avez sur votre ordinateur est défini par l'addition des diffs des commits parents (appliquées chronologiquement).

Donc ici nous verrons les modifications apportées par 0+1+2+3

Organisations des commits

0
1
2
3

Si l'on change HEAD vers le commit 2, on pourra voir l'état des fichiers sans les modifications apportées par 3. (Seulement 0+1+2)

Il est donc possible de retourner dans le passé, pour voir l'état des fichiers avant telle ou telle autre modification.

Les branches

Il manque une dernière pièce avant de pouvoir vraiment utiliser Git, et ce sont les branches.

Les branches

Une suite de commits ne doit pas forcément être linéaire !

Chaque bifurcation démarre une nouvelle branche.

Dans notre cas, HEAD pointe vers 6, nos fichiers
contiendront les diffs de 0 + 1 + 2 + 5 + 6.

Le repository ("le dépôt" en 🇫🇷)

  • Endroit où notre code est stocké, ainsi que l'historique des versions et toutes les données relatives à git.
  • Généralement, un projet == un repo.

Des questions ?

Yay ! Si vous avez compris tout ça, on peut continuer.

Configuration de git pour la suite de cet atelier

git config --global user.name "Votre nom"
git config --global user.email "votre@email.com"
git config --global pull.rebase false
git config --global push.autoSetupRemote true
git config --global init.defaultBranch main

Premiers commits

Créez votre repo :

$ mkdir cool-repo
$ cd cool-repo
$ git init
Dépôt Git vide initialisé dans /home/###/cool-repo/.git/

Un dépôt vide à été créé avec succès ! Et il ne contient donc aucun commit !

Premiers commits

Créons maintenant un fichier, appelé "README.md" (ou autrement, comme vous voulez !)

$ touch README.md

Premiers commits

Ensuite, écrivez ce que vous voulez dedans.
(Ouvrez le avec bloc notes, ça marche très bien)

Premiers commits

Nous allons maintenant "enregistrer" cette modification dans
le dépôt git.

Le stage

+   Votre Modif

Working Repo

Local Git Repo


Le stage

+   Votre Modif

Working Repo

Stage

Local Git Repo


Permet de "préparer" ses commits. C'est un espace de travail pour les changements.

Le stage

Working Repo

+
Votre Modif
Stage

Local Git Repo


$ git add chemin/vers/mon/fichier

Le stage

Working Repo

+
Votre Modif
Stage

Local Git Repo

Vous pouvez visualiser le stage avec:

$ git diff --staged 

Et vous pouvez visualiser ce qui reste à y ajouter avec :

$ git diff 

Le stage

+
Votre Modif

Working Repo

Stage

Local Git Repo


Vous pouvez nettoyer le stage avec:

$ git reset

Le stage

Working Repo

Stage

Local Git Repo


Vous pouvez effacer tous vos changements avec:

$ git restore

⚠️ Cette opération modifiera les fichiers, vous perdrez donc tout le travail accompli !

Statut global

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   fichier-modifié-et-staged

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   fichier-modifié-mais-pas-stageed

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

no changes added to commit (use "git add" and/or "git commit -a")

Le stage

+ Une modification

Working Repo

+ Une autre modification
+ Encore une autre modification !!
Stage

Local Git Repo


Bref, une fois que tous vos changements sont sur le stage...
(il peut y en avoir autant que vous voulez)

Le stage

+ Une modification

Working Repo

Stage

Local Git Repo


Vous pouvez commit vos changements.

$ git commit -m "Modification de README.md" # Utilisez -m pour ajouter un titre au commit !

Le stage

0
1
2

Local Git Repo

Et ils seront ajoutés aux précédents !

Le log

  • Au final, notre code est une superposition de ces changements (commits) en ordre chronologique.
$ git log
commit 3e54... (HEAD -> main, origin/main, origin/HEAD)
Author: Tux <info@louvainlinux.org>
Date:   Thu Feb 29 14:06:18 2024 +0100

    Dernier commit

commit de92ddfcc4f6c9e06dfc148f681e35aeca32ac01
Author: Tux <info@louvainlinux.org>
Date:   Thu Feb 29 14:05:25 2024 +0100

    Premier commit

Le remote repository

  • Est la version du dépôt git qui est stocké sur un serveur.
  • C'est là que tous les changements sont partagés entre les personnes.

Le remote repository

Repo Local  
0
1
2
Repo Remote
0
1
2

Mais comment "envoyer" nos changements ?

Push

Repo Local  
0
1
2
Repo Remote
0
1
2
$ git push
Repo Locale  
0
1
2
Repo Remote
0
1
2

Et si maintenant quelqu'un d'autre a commit des changements entre temps ?

Repo Locale  
0
1
2
Repo Remote
0
1
2
$ git pull

Recap

Ajouter vos changements au stage

$ git add -A

Commit les changements vers le dépôt git local

$ git commit -m "j'ai fait un changement"

Ajouter les changements au dépôt git distant

$ git push

Récupérer les changements faits par d'autres contributeurs

$ git pull

Création de votre sandbox

Status: Pas encore OK

Recap (1/2)

  • Stage : Endroit où les changements qui doivent être ajoutés à un commit sont préparés.
  • Commit : L'acte de prendre une « photo » des changements sur le stage et de mettre un nom dessus.
  • Log : La liste de tous les commits.
  • Le dépôt local : La version locale de votre projet
  • Le dépôt distant : La version en ligne de votre projet

Un exemple concret !

Démo en live de ce que je viens d'expliquer.

Exercices git

Assurez-vous de bien être dans le dossier de votre repo :

$ pwd
/home/tux/repo-##

Mise en place du dépôt distant

Afin de pouvoir travailler en collaboration, il va falloir ajouter un dépôt distant !


$ git remote add origin 

Le nom origin est une convention, mais vous pouvez toujours choisir !

Exercice 1 : Les bases

  • Modifier le fichier README.md
  • "Stage" les changements : git add README.md
  • "Commit" les changements : git commit -m "descriptif de mes changements"
  • "Push" les changements : git push

Status: Pas encore OK

Exercices sur la collaboration

Merges, conflits, résolutions

Exercice 2 : Changements sur le dépôt distant

Status: Pas encore OK

Exercice 2 : Changements sur le dépôt distant

Contexte : quelqu'un a push des changements après vous.
Essayez de faire un nouveau commit.

Exercice 2 : Changements sur le dépôt distant

$ git push
[main 7c64a36] test
To https://git.louvainlinux.org/repo-##
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://git.louvainlinux.org/repo-##'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Exercice 2 : Changements sur le dépôt distant

  • "Pull" les changements du remote : git pull
  • Vous verrez un nouveau fichier en faisant ls
  • Faites un git log et vous verrez qu'un commit a été ajouté avant le votre.
  • "Push" votre commit et ça marchera : git push

Status: Pas encore OK

Exercice 3 : Conflits de merge (fusion en français)

Status: Pas encore OK

Exercice 3 : Conflits de merge

Contexte : quelqu'un a push un commit qui a modifié quelque chose qu'un commit à vous a aussi modifié.

Exercice 3 : Conflits de merge

  • Changez la première ligne de youpi.txt vers ce que vous voulez.
  • Committez ce changement.
  • Essayez de « push » git push
    => Cela ne marche pas
  • « Pull » les derniers changements du dépôt distant : git pull
$ git pull
Auto-merging youpi.txt
CONFLICT (content): Merge conflict in youpi.txt
Automatic merge failed; fix conflicts and then commit the result.

Exercice 3 : Conflits de merge

  • Ouvrez youpi.txt et gardez ce que vous voulez :
<<<<<<< HEAD
# Mon nouveau titre
=======
PILOU PILOU
>>>>>>> main

Exercice 3 : Conflits de merge

  • Committez la resolution du conflit :
git add youpi.txt
git commit -m "merge: Merge from main"
git push

Status: Pas encore OK

Travail de groupe

Pour cette partie de la présentation, construisez des groupes de 2.
Choisissez le dépôt que vous préférez - vous allez à présent tous les deux travailler dessus.
Votre partenaire va devoir cloner votre dépôt (ou vous devrez cloner le sien le cas échéant)


$ git clone 


Exercice 4 : Générer un merge conflict

Faites en sorte qu'il y ait un merge conflict :

  • Modifiez tous les deux la même ligne.
  • Faites tous les deux un commit et essayez de push.
  • L'un d'entre vous devra pull et résoudre le conflit.

Ensuite, inversez les rôles !

Branches

  • Permettent que chacun travaille "dans son coin".
  • Les changements parallèles sont fusionnés en une fois plutôt qu'après chaque commit.
  • Permettent de tester des changements avant de les faire passer en production.
  • La branche principale s'appelle main.

Lister les branches

On peut voir une liste des branches :

$ git branch
* main
  branch2

L'étoile indique sur quelle branche on est.

Changer de branche

On peut changer notre branche courante :

$ git checkout branch2
$ git branch
  main
* branch2

Nouvelle branche

On peut créer une nouvelle branche et la sélectionner comme branche courante en une seule manipulation :

$ git checkout -b branch3
$ git branch
  main
  branch2
* branch3

Visualisation des branches

On peut visualiser les branches :

$ git log --oneline --decorate --graph --all

# C'est un peu trop long pour taper ici,
# regarder plutôt la jolie image à droite.

Merge d'une branche

On peut merge une branche :

$ git checkout main
$ git merge branch2
$ git merge branch3

Et l'effacer ensuite :

$ git branch -d branch2
$ git branch -d branch3

Conflits de merge

Commit A

Recette de cookies:
1. 1 oeuf
- 2. carottes 
+ 2. du chocolat 
3. 500g de farine
4. Herbes de provence
    

Commit B

Recette de cookies:
1. 1 oeuf
- 2. carottes 
+ 2. du beurre 
3. 500g de farine
4. Herbes de provence
    

Branches distantes

On peut push nos branches pour les utiliser autre part :

$ git push

Branches distantes

Exercice 5 : Branches

  • Toujours en groupes de deux, créez chacun une branche ;
  • Faites quelques commits sur vos branches respectives avant de push vos modifications ;
  • Pull les changements de l'autre ;
  • Fusionnez la branche de l'autre (et résolvez les conflits s'il y en a).
  • Push le merge.

Étiquette git

Ne pas push des gros blobs binaires

  • Git est principalement conçu pour du texte.
  • Éviter de push de gros fichiers s'ils ne constituent pas la "source" du projet (i.e. si l'utilisateur sait le générer lui-même, ça n'a pas lieu d'être sur git).

Solution : .gitignore

Fichier à la racine du dépôt qui contient une liste des chemins à ignorer lors des stagings :

je/veux/surtout/pas/commit/ce/dossier

# "*" veut dire "main.o", mais aussi "dfkjghdkfg.o"
# ou encore "sedidhoi.o"

*.o

Avoir la diff la plus petite

  • Ne pas modifier des choses qui ne sont pas pertinentes.
  • Exemple : Changer le formattage d'un fichier auquel on a autrement pas touché, même s'il est incorrect.
  • But : Avoir la diff la plus petite. Une petite diff est plus facile à review et à "blâmer" (on verra ça plus tard).

Pas de "trailing whitespaces" (espaces flottants)

  • Ne pas laisser des espaces blancs à la fin des lignes.
  • git diff les affichera même en rouge pour ne pas passer à côté :

Avoir un newline (\n) à la dernière ligne

Sur VS Code, ajouter dans settings.json :

{
	"files.insertFinalNewline": true
}

Pourquoi ce n'est pas activé par défaut ? Un mystère...
Important car sinon une diff qui ajoute une ligne en modifiera deux, vu qu'il faut aussi ajouter un retour à la ligne à la précédente.

Contribution à un dépôt Open Source

Maintenant on va mettre ce que vous avez appris en pratique !

Créer un compte GitHub

Mettre en place les clefs SSH (authentification)

$ ssh-keygen -t ed25519 -P "" # Il est recommandé de protéger la clé par mot de passe en retirant ce qui suit (et inclus) le -P
# Appuyez sur ENTER
$ cat ~/.ssh/id_ed25519.pub

Copier la sortie de cette commande.

Ajouter la clef SSH sur GitHub

Une fois dans les paramètres, allez sur "SSH and GPG keys".

Ajouter la clef SSH sur GitHub

Appuyez sur "New SSH key".

Ajouter la clef SSH sur GitHub

Collez votre clef SSH public.
Soyez sûr de bien copier id_ed25519.pub et pas id_ed25519 !

Créer un dépôt sur GitHub

Ajouter un second dépôt distant

$ git remote
origin
$ git remote add github ssh://git@github.com/tux/mon-repo
$ git remote
origin
github
$ git push github

Un exemple concret !

Démo en live de ce que je viens d'expliquer.

Contribuer à un dépôt Open Source

On va utiliser https://github.com/firstcontributions/first-contributions, qui est un projet construit pour présenter aux gens les contributions Open Source.

Fork

Faire ses changements

$ git clone ssh://git@github.com/tux/first-contributions
$ cd first-contributions

Ajoutez votre nom ou ce que vous voulez au fichier README.md.

$ git add README.md
$ git commit -m "Mes changements"
$ git push

Ouvrir une PR (Pull Request)

Un exemple concret !

Démo en live de ce que je viens d'expliquer.

Features avancées

Merci pour votre attention !

Les slides sont disponibles en ligne :

https://git.louvainlinux.org

Would like to make this pure html to make it easy to change

Hors sujet ?