<style>
.slides {
font-size: 3rem;
background: url('https://images.unsplash.com/photo-1556075798-4825dfaaf498?q=80&w=2076&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D') center/cover no-repeat;
}
.slides > section {
position: absolute;
inset: 0;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
display: grid;
place-content: center;
box-sizing: border-box;
}
.slides > section:first-of-type {
font-size: 8rem;
}
.slides h1, .slides h2, .slides h3,
.slides h4, .slides h5, .slides h6,
h1, h2, h3, h4, h5, h6 {
color: #e74c3c;
}
.slides strong, .slides em {
color: #ff9676;
}
.slides pre code {
width: auto;
max-height: initial;
}
.slides code {
color: #ffbd96;
font-style: italic;
}
.slides p {
padding: 0 2.4rem;
}
.slides .alert {
width: 90%;
margin: auto;
}
.slides ul, .slides ol {
width: calc(100% - 4rem);
}
html, body, .ui-content {
color: #ecf0f1;
}
.markdown-body h1, .markdown-body h2,
.markdown-body h3, .markdown-body h4,
.markdown-body h5, .markdown-body h6 {
color: #ecf0f1;
border-bottom-color: #ffffff4d;
}
.markdown-body img {
background-color: transparent;
}
.ui-toc-dropdown {
background-color: #2c3e50;
}
.ui-toc-label.btn {
background-color: #192b38;
color: #fff;
}
.ui-toc-dropdown .nav>.active>a,
.ui-toc-dropdown .nav>li>a:hover,
.ui-toc-dropdown .nav>li>a:focus {
color: #fff;
border-left: 2px solid #fff;
}
.expand-toggle:hover,
.expand-toggle:focus,
.back-to-top:hover,
.back-to-top:focus,
.go-to-bottom:hover,
.go-to-bottom:focus {
color: #fff;
}
.markdown-body blockquote {
color: #bcbcbc;
}
.markdown-body table tr {
background-color: #4b5f70;
}
.markdown-body table tr:nth-child(2n) {
background-color: #3e4f5f;
}
.markdown-body code, .markdown-body tt {
color: #f0f0f0;
background-color: rgba(230, 230, 230, 0.3);
}
a, .open-files-container li.selected a {
color: #3498db;
}
</style>
# Git
---
# Gestion de versions
## Sommaire
---
<style>
.columns {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 2rem 0;
}
.column {
flex: 1;
margin: 0 1rem;
min-width: 200px;
}
</style>
<div class="columns">
<div class="column">
### 1. Introduction
- Présentation de Git
- Gestion de versions (VCS vs DVCS)
- Fonctionnement interne
- Empreinte SHA-1
### 2. Commandes de base
- Initialisation d’un dépôt
- Ajout et validation
- Visualisation de l’historique
- Commandes essentielles
### 3. Zones et états des fichiers
- Copie de travail, zone de transit, dépôt local
- Différents états d’un fichier
- Ignorer, déplacer ou supprimer des fichiers
</div>
<div class="column">
### 4. Branches
- Création et basculement
- Fusion et rebase
- Types de branches (thématiques, longues)
- Gestion des conflits
### 5. Travail collaboratif
- Hébergement Git (GitHub, GitLab, Bitbucket)
- Dépôts distants
- Pull, Push, Fetch, et Clone
- Pull requests et révisions de code
### 6. Gitflow et workflows
- Branches principales et temporaires
- Modèles de branches
- Stratégies de fusion (Fast Forward, Squash, etc.)
</div>
</div>
---
<div class="columns">
<div class="column">
### 7. Commandes avancées
- Git stash et cherry-pick
- Git reset vs git revert
- Recherche avec git log et reflog
### 8. Outils et intégration
- CLI vs IDE
- Outils graphiques (SourceTree, GitKraken, etc.)
- Git hooks
- Gestion des fichiers volumineux (Git LFS)
</div>
<div class="column">
### 9. Exercices pratiques
- Gestion des branches
- Résolution de conflits
- Collaboration avec dépôt distant
### 10. Ressources
- Documentation officielle
- Simulateurs interactifs
- Cheat sheets et guides avancés
</div>
</div>
---
# Présentation
**Git** est :
- un logiciel de ***gestion de versions décentralisé*** (DVCS)
- un logiciel libre créé par Linus Torvalds en 2005
- Site officiel : https://git-scm.com

:::info
C’est le logiciel de gestion de versions le plus populaire devant Subversion (svn) qu’il a remplacé avantageusement.
:::
---
# Quelques ressources
- Manuel de référence : http://book.git-scm.com/docs
- Pro Git (fr) : http://git-scm.com/book/fr/v2
- Git Community Book (fr) : https://alexgirard.com/git-book/
- ExplainGit est un simulateur permettant d’expérimenter visuellement le résultat des commandes qui agissent directement sur le dépôt Git. Il ne simule ni le répertoire de travail ni l’espace d’index, mais uniquement le dépôt.
- (fr) : https://gauthier.frama.io/explain-git-with-d3/
- (en) : https://onlywei.github.io/explain-git-with-d3/
- Learn Git Branching (fr) : https://learngitbranching.js.org/?locale=fr_FR
---
# Système de gestion de versions (VCS)
- Le VCS (Version Control System) gère l’ensemble des versions (*« révision »* ou modification) d’un ou plusieurs fichiers (généralement en texte)
- Le VCS enregistre l’évolution d’un ensemble de fichiers au cours du temps dans un *historique*
- Les fichiers versionnés sont stockés sur un *dépôt* (repository)
- Essentiellement utilisée dans le développement logiciel, elle concerne surtout la gestion des codes source
:::info
Les différentes versions (ou révisions) sont nécessairement liées à travers des modifications : une modification est un ensemble d’ajouts, de modifications, et de suppressions de données.
:::
---
# Mécanismes de base d’un VCS
La gestion de version repose sur deux mécanismes de base :
- un *calcul de la différence* entre deux versions
- *diff* : Compare des fichiers ligne à ligne
- *patch* : Utilise la différence entre deux fichiers pour passer d’une version à l’autre
- un *gestionnaire d’historique des diff* pour conserver les modifications
Le principe est le suivant : on passera de la version N à la version N+1 en appliquant une modification M. Un logiciel de gestion de versions applique ou retire ces modifications une par une pour fournir la version du fichier voulue.
---
# VCS vs DVCS
Un **système de gestion de version** ou **VCS** (Version Control System) :
- maintient l’ensemble des versions d’un logiciel
- conserve l’historique (les révisions successives) du projet dans un seul dépôt (repository) qui fait référence : possibilités de revenir en arrière, de voir les changements
- facilite la collaboration entre les intervenants : chacun travaille avec son environnement, plusieurs personnes travaillent sur les mêmes fichiers simultanément
- fournit des outils pour gérer le tout.
Un *DVCS* (Distributed Version Control) offre les mêmes services qu’un VCS sur une **architecture décentralisée** (ou distribuée).
---
# Comparatif : Versioning centralisé vs distribué
---
## Centralisé
### Description
- Un seul dépôt de fichiers fait référence.
- Les clients n'ont qu'une version des fichiers.
- Chaque modification nécessite de contacter le serveur.
### Points forts
- Simple à comprendre.
- Idéal pour les petites équipes ou projets.
### Limites
- Dépendance au serveur central (pas de réseau = pas de travail).
- Risques accrus en cas de panne du serveur.
---
## Distribué
### Description
- Chaque client possède une copie complète de l’historique.
- Les clients peuvent travailler localement sans dépendre d'un serveur.
### Points forts
- Plus rapide pour les opérations locales.
- Plus résilient : chaque copie est une sauvegarde complète.
### Limites
- Moins adapté aux fichiers binaires volumineux.
- Historique potentiellement plus lourd à gérer.
---
# Git vs Subversion

---
# Fonctionnement interne
Le *dépôt Git* contient l’historique des instantanés (commits). C’est une base de "données" (d’objets) qui peut contenir *quatre types d’objets* :
- L’objet ***blob*** (binary large object) représente le contenu d’un fichier (chaque révision d’un fichier = objet blob unique).
- L’objet ***tree*** décrit une arborescence de fichiers. Il est constitué d’une liste d’objets de type blobs (avec les informations tel que le nom du fichier et les permissions). Il peut contenir d’autres objets trees pour représenter les sous-répertoires.
----
- L’objet ***commit*** correspond à une arborescence de fichiers (tree) enrichie de métadonnées comme un message de description, le nom de l’auteur, etc.
- L’objet ***tag*** est une manière de nommer arbitrairement un commit spécifique pour l’identifier plus facilement.
Git utilise des *index* (une somme de contrôle calculée avec la fonction de hachage *SHA-1*) pour référencer les objets de la base.
---
# Empreinte SHA-1
- Une empreinte SHA-1 est une chaîne de caractères composée de 40 caractères hexadécimaux (un *« hash »* de 160 bits) calculée en fonction du contenu du fichier. Dans Git :
- C’est une signature unique qui sert de référence (une clé, un index).
- Il est possible d’utiliser une empreinte SHA-1 courte (au moins 4 caractères) lorsqu’elle ne correspond pas à plusieurs commits.
- En règle générale, entre 8 et 10 caractères sont largement suffisants pour assurer l’unicité dans un projet.
```bash=
$ shasum -a 1 sam.txt
03a35cac40a7d2da4f4d5bc1d7bf1cdc9f246f84 sam.txt
$ echo "Fin" >> sam.txt
$ shasum -a 1 sam.txt
29297c711b070e02e249044a8b4ec194b6bbb5e1 sam.txt
```
---
# Historique
Git stocke un instantané (un commit) de la représentation de tous les fichiers du projet dans une structure hiérarchisée. L’instantané pointe également vers un ou plusieurs ***objets commits parents***.

---
# Les commandes
- Git est un ensemble de commandes indépendantes dont les principales sont : git init, git clone, git add, git status, git diff, git commit, git checkout, git merge, git log etc.
- Liens :
- https://training.github.com/downloads/fr/github-git-cheat-sheet/
- https://ndpsoftware.com/git-cheatsheet.html
- https://www.julienkrier.fr/articles/git-cheat-sheet
- Demander de l’aide : man git, git help, git help \<commande>
---
# Bonnes pratiques Git
### 1. Commits
- Effectuez **des commits petits et fréquents**.
- **Un commit = une fonctionnalité ou un correctif**.
- Rédigez des messages explicites :
- Exemples :
- ✅ "Fix bug #42: handle null pointer in login module."
- ❌ "Modifications diverses."
### 2. Push & Pull
- Effectuez des pull réguliers pour limiter les conflits.
- Push avant de quitter pour permettre à l'équipe de continuer le travail.
---
# Premier pas
### Installation Windows
- Direction le site de Git : https://git-scm.com/
<br>
### Installation Debian / Ubuntu
```bash=
$ sudo apt-get install git gitk
$ git --version
git version X.Y.Z
```
<br>
### Installation Mac avec homebrew
```bash=
$ brew install git
git version X.Y.Z
```
----
## Configuration
```bash=
$ git config --global user.name "<votre nom>"
$ git config --global user.email "<votre email>"
$ git config --global core.editor vim
$ git config --global color.diff auto
$ git config --global color.status auto
$ git config --global color.branch auto
$ cat $HOME/.gitconfig
$ git config --list
```
---
# En résumé
- La fonction principale de Git est de *suivre les différentes versions d’un projet*.
- Un projet est un ensemble de fichiers.
- Le *commit* (ou instantané) est l’élément central de Git.
- Un *commit* représente un ensemble cohérent de modifications sur le projet.
---
# Les zones
On distingue trois zones :
| | | |
|:----------------:|:---------------:|:-----------:|
| Copie de travail | Zone de transit | Dépôt local |

---
# Les différentes zones
- le **répertoire de travail** (working directory) : un répertoire du système de fichiers qui contient une extraction unique d’une version du projet pour pouvoir travailler
- **l’index** ou « zone de transit » (staging area) : un simple fichier (.git/index) qui stocke les informations concernant ce qui fera partie du prochain instantané (commit)
- le **dépôt local** (local repository) : un répertoire caché (.git/) qui stocke tout l’historique des instantannés (commits) et les méta-données du projet
- On peut considérer qu’il existe une quatrième zone nommée "remise" qui s’utilise avec la commande git stash.
---
# Les états d’un fichier
Les différents états d’un fichier :

----
## Les différents états d’un fichier
- *non suivi* ou non versionné (untracked) : aucun instantané existe pour ce fichier
- *non modifié* (unmodified) : non modifié depuis le dernier instantané
- *modifié* (modified) : modifié depuis le dernier instantané mais n’a pas été indexé
- *indexé* (staged) : modifié et ajouté dans la zone d’index
- *validé* (committed) : une version particulière d’un fichier
:::info
Pour obtenir l’état des fichiers du répertoire de travail (working directory), on utilise (très souvent) la commande git status
:::
---
# Initialiser un dépôt git
- Création d’un répertoire
```bash=
$ mkdir tp-git_1
mkdir: création du répertoire 'tp-git_1'
$ cd ./tp-git_1
```
- Initialisation d’un dépôt git
```bash=
$ git init
Dépôt Git vide initialisé dans $HOME/tp-git_1/.git/
$ ls -al
...
drwxrwxr-x 7 tv tv 4096 juil. 28 10:58 .git
# Pour l’instant, aucun fichier n’est encore versionné.
```
---
# Travailler avec git
- on édite des fichiers dans le répertoire de travail (working directory)
- on indexe les fichiers modifiés, ce qui ajoute des instantanés de ces fichiers dans la zone d’index (staging area) ;
- on valide les modifications, ce qui a pour effet de basculer les instantanés des fichiers de l’index dans le dépôt local (local repository ).

---
# Opérations sur les fichiers
- Ignorer des fichiers : il faut les ajouter dans un fichier spécial : *.gitignore*
<br>
:::info
Pour nettoyer son répertoire de travail, on peut utiliser la commande *git clean* qui permet de supprimer les fichiers non-suivis qui ne sont pas ignorés.
:::
- Effacer des fichiers : commandes `git rm` et `git rm --cached`
- Déplacer/Renommer des fichiers : commande `git mv`
---
# Visualiser des différences
La commande git diff (voir aussi git difftool) pour visualiser les lignes exactes qui ont été ajoutées, modifiées ou effacées :
- Voir les différences avec l’index
```bash=
$ git diff
```
- Voir les différences avec le dernier commit
```bash=
$ git diff --staged
```
La commande *git diff \<commit>* sert à visualiser les modifications présentes dans le répertoire de travail par rapport au \<commit> indiqué.
---
# Visualiser l’historique
Après avoir créé plusieurs instatanés (commits), il est possible de consulter l’historique avec la commande git log. C’est une commande importante et puissante disposant de nombreuses options :
- *git log -\<nombre>* Limiter le nombre de commits
- *git log --oneline* Affiche chaque commit sur une seule ligne
- *git log -p* Affiche la différence complète de chaque commit
- *git log --graph --decorate* Affiche sous forme de graphe
- *git log --stat* Affiche avec des statistiques
- *git log -\- \<fichier>* Affiche uniquement les commits du fichier
- *git log \<depuis>..<jusqu’à>* Affiche les validations qui se produisent entre deux commits en utilisant une référence
Voir aussi :
- *git blame \<fichier>* Affiche qui a modifié le fichier et quand
- *git show \<objet>* Affiche un objet du dépôt
---
# Annuler des actions
- *git commit --amend* pour modifier le dernier commit
- *git reset HEAD \<fichier>* pour désindexer un fichier
- *git checkout -\- \<fichier>* pour annuler les modifications dans la copie de travail
- *git revert* pour inverser un *commit*
Voir aussi :
- *git reset --soft HEAD~* pour annuler le dernier `git commit`
- *git reset --mixed HEAD~* pour annuler le dernier `git add` et `git commit`
- *git reset --hard HEAD~* pour annuler les modifications dans la copie de travail et le dernier `git add` et `git commit`
---
# Commandes avancées
### git stash
- **Utilité :** Mettre de côté des modifications sans les committer.
- Commandes principales :
```bash
git stash # Sauvegarder les modifications non commitées
git stash list # Voir les stashes enregistrés
git stash apply # Restaurer un stash (sans le supprimer)
git stash pop # Restaurer et supprimer le stash
```
---
### git cherry-pick
- **Utilité :** Appliquer un commit spécifique sur une autre branche.
- Exemple :
```bash
git cherry-pick <commit-hash>
```
- ⚠ Peut dupliquer les commits. Préférez `git merge` si possible.
---
### git reset vs git revert
- **git reset** : Revenir à un état précédent en modifiant l’historique local.
```bash
git reset --soft HEAD~1 # Garde les changements dans l'index
git reset --hard HEAD~1 # Supprime toutes les modifications
```
- **git revert** : Annuler un commit en créant un nouveau commit.
```bash
git revert <commit-hash>
```
- **Différence clé :** `git revert` conserve l’historique, contrairement à `git reset`.
---
# Étiqueter des versions
Git utilise deux types principaux d’étiquettes (tags) :
- *légère* : un pointeur sur un commit spécifique. Celles-ci se réduisent à stocker la somme de contrôle d’un commit dans un fichier
- *annotée* (avec l’option -a) : un objet *tag* dans la base de données
```bash=
# légères
$ git tag v1.0
$ git tag -a 1.1 -m 'La version 1.1'
$ git tag
1.0
1.1
$ git show 1.0
$ git show 1.1
```
Il est possible d’étiqueter après coup en spécifiant le commit : `git tag -a v1.2 <commit>`
---
# Publier une version
- Pour publier une version, il est nécessaire de créer une archive à partir d’un commit (généralement une étiquette de version).
- La commande dédiée à cette action est git archive :
```bash=
# Modèle :
# git archive --prefix=src-directory-name tag --format=zip > 'git describe master'.zip
$ git archive --prefix='tp-git_1-sam/' 1.0 | gzip > tp-git_1-sam.tar.gz
$ git archive --prefix='tp-git_1-sam/' 1.0 --format=zip > tp-git_1-sam.zip
```
Il est possible de copier un dépôt avec la commande : `cp -Rf <source> <destination>`.
Git fournit surtout la commande `git clone` pour cela.
---
# Utiliser le mode interactif
Git propose quelques scripts qui "guident" les opérations en ligne de commande avec l’option -i ou --interactive. Le mode interactif s’utilise principalement avec les commandes :
- `git add --interactive` : pour choisir les fichiers ou les parties d’un fichier à incorporer à un commit
- `git clean --interactive` : pour choisir les fichiers qui seront supprimés du répertoire de travail
- `git rebase --interactive` : pour choisir les commits à "rejouer"
- Réordonner les commits
- Écraser un commit
- Diviser un commit
- Supprimer un commit
---
# En résumé
- Éditer des fichiers : *vim* ou un *EDI/IDE*
- Ajouter les changement : `git add <fichier>`
- Valider les changements : `git commit -m "Message"`
Les commandes que l’on utilise tout le temps :
- git status
- git log ...
---
# Les branches
----
- Créer une branche signifie diverger de la ligne principale de développement et continuer à travailler sans impacter cette ligne.
- Une branche représente une *ligne de développement indépendante*.
- Mais techniquement, une branche dans Git est simplement un pointeur déplaçable vers un *commit*.
- À chaque validation, le pointeur de la branche avance automatiquement pour pointer vers le dernier des commits réalisés.
- Le pointeur de la tête de la branche actuelle se nomme *HEAD*
:::info
La branche *master* ou *main* n’est pas une branche spéciale. Elle est identique à toutes les autres branches. La seule raison pour laquelle chaque dépôt en a une est que la commande git init la crée par défaut.
:::
---
# Créer et basculer de branche
- Créer une nouvelle branche : `git branch <nom-branche>` (cela crée simplement un nouveau pointeur vers le commit courant)
- Basculer sur une branche existante : `git checkout <nom-branche>` (cela déplace HEAD pour le faire pointer vers la branche)
- En une seule commande : `git checkout -b <nouvelle-branche>`
:::info
Il est important de noter que lorsque l’on change de branche avec Git, *les fichiers du répertoire de travail sont modifiés*. Si la copie de travail ou la zone d’index contiennent des modifications non validées qui sont en conflit avec la branche à extraire, Git n’autorisera pas le changement de branche. Le mieux est donc d’avoir une copie de travail propre au moment de changer de branche.
:::
---
# Fusionner une branche
- Une fois le travail réalisé (terminé et testé) dans la branche, il est prêt à être *fusionné* dans la branche master. On réalise ceci au moyen de la commande `git merge`.

- À présent que le travail a été fusionné, on n’a plus besoin de la branche. On peut la supprimer avec la commande `git branch -d <nom-branche>`
---
# Rebaser
- En utilisant le *rebasage*, il est possible de conserver un historique linéaire après une fusion.
- La commande `git rebase` permet de changer la « base » (le commit de départ) de la branche courante. La nouvelle « base » devient le dernier commit de la branche passée en argument de la commande.
----

- Git a « rejoué » chacun des *commits* de la branche dev sur la tête de la branche master.
---
# Travailler avec les branches
Cela permet :
- de gérer plusieurs branches en parallèle et ainsi de cloisonner les travaux et d’éviter ainsi de mélanger des modifications du code source qui n’ont rien à voir entre elles.
- de conserver une version du logiciel prête à être livrée à tout instant puisqu’on ne fusionne que lorsque le développement d’une branche est bien terminé.
:::info
Dans Git, créer, développer, fusionner et supprimer des branches plusieurs fois par jour est un travail "normal". Un dépôt Git peut maintenir de nombreuses branches de développement.
:::
---
# Différentes types de branches
On peut distinguer plusieurs types de branches :
- les **branches au long cours** (permanentes) : ce sont des branches ouvertes en permanence pour les différentes phases du cycle de développement.
- les **branches thématiques** (temporaires) : une branche thématique est une branche ayant une courte durée de vie créée et utilisée pour une *fonctionnalité* ou une *tâche particulière* (un correctif par exemple). On y réalise quelques commits et on supprime la branche immédiatement après l’avoir fusionnée dans la branche principale. Les branches thématiques sont utiles quelle que soit la taille du projet.
- Voir aussi : les branches de suivi
:::info
De nombreux développeurs travaillent avec Git en utilisant une méthode de développement basée sur les branches (par exemple Gitflow).
:::
---
# Graphe d’historique

---
# Le pointeur de référence HEAD
- `HEAD` est une référence symbolique pointant vers l’endroit (un commit) où l’on se trouve dans l’historique. Si on fait un commit, HEAD se déplacera.
- `HEAD~` désigne le premier ancêtre de la pointe de la branche actuelle. `HEAD~` est l’abréviation de `HEAD~1`. `HEAD~n` désigne le n-ième ancêtre.
- `HEAD^` désigne le premier parent immédiat de la pointe de la branche actuelle. `HEAD^` est l’abréviation de `HEAD^1`. `HEAD^2` désigne le deuxième parent lorsqu’il y a un commit de fusion.
- Pour un commit avec un seul parent, `HEAD~` et `HEAD^` signifient la même chose.
---
# Exemple : HEAD

---
# En résumé
- Créer une branche thématique et basculer dessus : `git branch <branche>` puis `git checkout <branche>` (ou `git checkout -b <branche>`)
- Éditer des fichiers : vim ou un EDI/IDE
- Ajouter les changement : `git add <fichier>`
- Valider les changements : `git commit -m "Message"`
- Basculer sur la branche principale et fusionner la branche thématique : `git checkout master` puis `git merge <branche>`
- Supprimer la branche thématique : `git branch -d <branche>`
Les commandes que l’on utilise tout le temps :
- git status
- git log ...
- git branch ...
---
# Git hébergé
----
Il est possible d’héberger des projets Git sur un site externe dédié à l’hébergement. Quelques hébergeurs :
- **GitHub** est un service web d’hébergement (lancé en 2008) et de gestion de développement de logiciels, utilisant le logiciel de gestion de versions Git. Site officiel : https://github.com/
- **GitLab** est un logiciel libre de forge basé sur Git proposant les fonctionnalités de wiki, un système de suivi des bugs, l’intégration continue et la livraison continue. Site officiel : https://about.gitlab.com/
- **Bitbucket Cloud** est un service web d’hébergement et de gestion de développement logiciel utilisant le logiciel de gestion de versions Git. Site officiel : https://bitbucket.org/
:::info
Liste : https://git.wiki.kernel.org/index.php/GitHosting
:::
---
# Notion de dépôt distant
Un *dépôt distant* est un dépôt hébergé sur un serveur, généralement sur Internet.

:::info
Un dépôt distant peut servir à la sauvegarde et/ou au partage du code d’un projet.
:::
---
# Interagir avec un dépôt distant
Des commandes spécifiques seront utilisées pour synchroniser les dépôts local et distant :
- `git clone` permet d’obtenir une copie d’un dépôt Git existant.
- `git push` publie ("pousse") les nouveaux commits du dépôt local sur le dépôt distant.
- `git fetch` récupère l’ensemble des commits présents sur le le dépôt distant et met à jour le dépôt local. Elle ne modifie pas le répertoire de travail.
- `git pull` consiste essentiellement en git fetch suivi par git merge. Le répertoire de travail peut donc être modifié.
----

---
# Interagir avec GitHub
Il est possible d’interagir avec un dépôt sur GitHub de plusieurs manières :
- L’URL d’accès au dépôt en SSH sera de la forme : `git@github.com:<utilisateur>/<depot>.git`
https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh
- L’URL d’accès au dépôt en HTTPS sera de la forme : `https://github.com/<utilisateur>/<depot>.git`
https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token
- La commande gh permet l’utilisation de GitHub en la ligne de commande (CLI) : `gh repo clone <utilisateur>/<depot>.git` https://cli.github.com/
---
# Authentification sur GitHub
### Nouveaux standards (Post-2021)
- **Fin des mots de passe classiques :**
- **Clé SSH** :
```bash
ssh-keygen -t ed25519 -C "email@example.com"
```
Ajoutez la clé publique sur GitHub : [Guide GitHub](https://docs.github.com/en/authentication/connecting-to-github-with-ssh).
- **Token d'accès personnel (PAT)** :
- Utilisé comme mot de passe.
- [Guide GitHub](https://docs.github.com/en/authentication/creating-a-personal-access-token).
---
# Cloner un dépôt distant
La commande git clone effectuera les actions suivantes :
- créé un répertoire du nom du dépôt existant, initialisé avec un répertoire *.git* à l’intérieur
- nomme automatiquement le serveur distant (*remote*) origin
- tire l’historique
- crée un pointeur sur l’état actuel de la branche main et l’appelle localement *origin/main*
- crée également une branche locale *main* qui démarre au même endroit que la branche *main* distante
---
# Associer un dépôt distant existant
Un dépôt distant (*remote repository*) doit exister sur GitHub par exemple :
```bash=
$ mkdir <depot>
$ cd ./<depot>
$ git init
$ git remote add origin git@github.com:<utilisateur>/<depot>.git
$ git branch -M main
$ git push -u origin main
$ git remote -v
origin git@github.com:<utilisateur>/<depot>.git (fetch)
origin git@github.com:<utilisateur>/<depot>.git (push)
```
---
# Branche de suivi
Une branche de suivi (*tracking branch*) est une branche locale qui est en relation directe avec une branche distante (*upstream branch*).
Les branches de suivi peuvent servir :
- à sauvegarder son travail sur la branche dans un dépôt distant
- partager son travail sur la branche avec d’autres développeurs
Voir aussi les options *--track*, *-u* ou *--set-upstream-to*, *--set-upstream* des commandes *checkout*, *branch* et *push*.
---
# Pull Request et Révision de code
**Pull Request** peut être traduit par *« Proposition de révision »* (PR) :
c’est-à-dire une demande de modification ou de contribution.
Les Pull Requests sont :
- une fonctionnalité facilitant la collaboration des développeurs sur un projet.
- un mécanisme permettant à un développeur d’informer les membres de l’équipe qu’il a terminé un « travail »(une fonctionnalité, une version livrable, un correctif, ...) et de proposer sa contribution au dépôt central.
- une notifcation aux développeurs pour qu’ils révisent le code puis le fusionnent (merge).
Pendant une *révision de code*, les développeurs peuvent discuter de la fonctionnalité (commenter le code, poser des questions, ...) et proposer des adaptations de la fonctionnalité en publiant des commits de suivi.
---
# Pull Request

---
# Travail collaboratif
Attention :
- Nettoyer son historique local avant de publier en effectuant un rebasage interactif avec `git rebase -i @upstream`
- Travailler à plusieurs sur une branche de fonctionnalité : faire `git pull --rebase` sur une branche de suivi obsolète
- Supprimer (si besoin) toutes ses modifications et commits locaux et récupérer un dépôt distant « propre » : `git fetch origin && git reset --hard origin/main`
---
# Rebasage interactif

---
# Stratégies de fusion
- **Avance rapide (Fast Forward)** : c’est la fusion utilisée par défaut par git merge si c’est possible. Git déplace (vers l’avant) les commits de la branche feature vers la branche destination *main* si il n’y a pas eu de nouveaux commits sur cette branche. On peut réaliser cette fusion avec l’option *--ff-only*.
- **Commit de fusion (merge commit)** : lorsque l’historique de développement a divergé, git merge réalise une fusion à trois sources (three-way merge) en utilisant les deux commits au sommet des deux branches (C4 et C5) ainsi que leur plus proche ancêtre commun (C2) pour créer un nouveau commit (C6). On peut réaliser cette fusion avec l’option *--no-ff*.
- **Squash** : on obtient un nouveau commit qui regroupe tous les commits de la branche. Pour réaliser cette fusion, il faut ajouter l’option *--squash*.
----
# Avance rapide (Fast Forward)

----
# Commit de fusion

----
# Squash

---
# Conflit de fusion
- Il est possible qu’une fusion (*merge*) ne puisse pas être réalisée automatiquement par Git.
- Cela arrive lorsqu’une même partie d’un fichier a été modifiée dans deux branches distinctes.
- Lorsque Git rencontre un conflit au cours d’une fusion, il l’indique dans les fichiers concernés avec des *délimiteurs* (<<<<<<<, ======= et >>>>>>>) qui marquent les deux côtés du conflit.
- Pour résoudre le conflit, il faut choisir une partie ou l’autre ou bien fusionner les deux contenus "à la main".
- On peut ensuite terminer la fusion (suivre les indications de git status) en faisant un `git commit`.
---
# workflow git
- Un ***workflow Git*** est une méthode, un processus de travail, une recette ou une recommandation sur la façon d’utiliser Git pour accomplir un travail de manière cohérente et productive.
- Il n’existe pas de processus standardisé sur la façon d’interagir avec Git.
- Il est important de s’assurer que l’équipe de projet est d’accord sur la façon dont le flux de modifications sera appliqué. Un *workflow* Git doit donc être défini.
- Il existe plusieurs *workflow* Git connus qui peuvent être utilisés : *workflow centralisé*, *workflow de branche de fonctionnalité*, *workflow Gitflow*, etc.
https://www.atlassian.com/fr/git/tutorials/comparing-workflows
---
# Gitflow
- Le *workflow Gitflow* définit un modèle de branchement strict conçu autour de la version du projet.
- Ce *workflow* n’ajoute pas de nouveaux concepts ou commandes.
- *Gitflow* permet de gérer les bugs (issues), les nouvelles fonctionnalités (features) et les versions (releases) en attribuant des rôles très spécifiques à différentes branches et définit comment et quand elles doivent interagir.
:::info
Il existe des extensions git-flow à Git pour intégrer le workflow Gitflow.
:::
---
# Modèle GitFlow
---
### Branches principales
- **main** : Contient uniquement les versions prêtes pour la production.
- **develop** : Branche d’intégration pour les nouvelles fonctionnalités.
### Branches temporaires
- **feature/xxx** : Pour le développement de nouvelles fonctionnalités.
- **release/xxx** : Pour stabiliser et préparer une version.
- **hotfix/xxx** : Pour corriger rapidement un bug en production.
### Commandes avec l’extension git-flow
- Initialisation :
```bash
git flow init
```
- Création d’une fonctionnalité :
```bash
git flow feature start <nom>
git flow feature finish <nom>
```
---
# Installation de Git Flow
---
### Installation sous macOS
1. Ouvrez votre terminal.
2. Installez Git Flow via Homebrew :
```bash
brew install git-flow
```
3. Vérifiez l’installation :
```bash
git flow version
```
---
### Installation sous Linux
#### Pour Debian/Ubuntu
1. Ouvrez votre terminal.
2. Installez Git Flow avec APT :
```bash
sudo apt-get install git-flow
```
3. Vérifiez l’installation :
```bash
git flow version
```
---
#### Pour d’autres distributions Linux
- Utilisez le gestionnaire de paquets de votre distribution.
- Exemple pour Arch Linux :
```bash
sudo pacman -S git-flow
```
---
### Installation sous Windows
1. Téléchargez un package manager comme [Chocolatey](https://chocolatey.org/).
2. Installez Git Flow :
```bash
choco install git-flow
```
3. Vérifiez l’installation :
```bash
git flow version
```
4. Alternative : Utilisez un client Git avec Git Flow intégré, comme SourceTree.
---
### Initialisation de Git Flow dans un projet
1. Accédez au répertoire de votre projet :
```bash
cd /chemin/vers/votre/projet
```
2. Initialisez Git Flow :
```bash
git flow init
```
3. Suivez les instructions pour définir les conventions de nommage des branches (par défaut : `main` et `develop`).
---
# Modèle de branches

---
# Rôles des branches
- pour les **branches permanentes** :
- La *branche master* stocke l’historique des versions officielles. Tous les commits de cette branche sont étiquetés avec un numéro de version (tags ).
- La *branche develop* est créée à partir de la branche master. Elle sert de branche d’intégration pour les fonctionnalités. Cette branche contiendra l’historique complet du projet.
----
- pour les **branches temporaires** :
- Les branches *features-xxxx* permettent de travailler sur des nouvelles fonctionnalités. Elles sont créées directement à partir de la branche develop et une fois le travail fini, fusionnées vers la branche develop.
- Les branches *release-xxxx* permettent de travailler sur une livraison (généralement des tâches dédiées à la documentation). On les crée à partir de develop puis on les fusionne dans master en leur attribuant un numéro de version (tag).
- Les branches *hotfix-xxxx* permettent de publier rapidement (hot) une correction (fix) depuis la branche master. Ces branches seront ensuite fusionnées vers la branche master et develop.
---
# Réalisation d’une fonctionnalité

---
# Réalisation d’une release

---
# Correction d’un bug

---
# CLI vs IDE
---
## Environnement de développement intégré (EDI ou IDE)
La plupart des environnements de développement intégre Git ou propose des extensions pour le faire. Le contrôle de source (SCM) dans VS Code :

---
# Les outils graphiques
Il existe de nombreuses interfaces graphiques permettant de gérer des projets Git :
- une interface web avec GitWeb
- une interface de visualisation détaillée et graphique avec gitk
Il existe également de nombreuses autres applications :
- qgit, Giggle, GitExtensions, TortoiseGit, SourceTree, GitEye, GitKraken ...
---
# Outils graphiques pour Git
### SourceTree
- Intègre Git avec une interface utilisateur.
- Fonctionnalités :
- Gestion des commits, branches, et conflits.
- Historique graphique.
- Téléchargement : [SourceTree](https://www.sourcetreeapp.com/).
### Visual Studio Code
- Intégration native de Git.
- Merge Editor pour résoudre les conflits facilement.
---
# GitEye

---
# Git LFS
### Qu’est-ce que c’est ?
- **Git Large File Storage** permet de versionner des fichiers volumineux (ex : binaires).
- Stocke des **pointeurs** à la place des fichiers eux-mêmes.
### Configuration
- Suivre un type de fichier :
```bash
git lfs track "*.jpg"
```
- Exemples de commandes :
```bash
git add .gitattributes
git add *.jpg
git commit -m "Add large files tracking."
git push
```
- Site officiel : [git-lfs.github.com](https://git-lfs.github.com).
---
# Les principales commandes 1
Git est un ensemble de commandes indépendantes dont les principales sont :
- `git init` crée un nouveau dépôt
- `git clone` clone un dépôt distant
- `git add` ajoute le contenu du répertoire de travail dans la zone d’index pour le prochain commit
- `git status` montre les différents états des fichiers du répertoire de travail et de l’index
- `git diff` montre les différences
----
# Les principales commandes 2
- `git commit` enregistre dans la base de données (le dépôt) un nouvel instantané avec le contenu des fichiers qui ont été indexés puis fait pointer la branche courante dessus
- `git branch` liste les branches ou crée une nouvelle branche
- `git checkout` permet de basculer de branche et d’en extraire le contenu dans le répertoire de travail
- `git merge` fusionne une branche dans une autre
- `git log` affiche la liste des commits effectués sur une branche
----
# Les principales commandes 3
- `git fetch` récupère toutes les informations du dépôt distant et les stocke dans le dépôt local
- `git push` publie les nouvelles révisions sur le dépôt distant
- `git pull` récupère les dernières modifications distantes du projet et les fusionne dans la branche courante
- `git tag` liste ou crée des tags ;
- `git stash` stocke de côté un état non commité afin d’effectuer d’autres tâches.
---
# Exercices pratiques
---
### Gestion des branches
1. Créez une nouvelle branche :
```bash
git branch feature/test
```
2. Basculez sur cette branche :
```bash
git checkout feature/test
```
3. Apportez des modifications au projet et effectuez des commits :
```bash
git add .
git commit -m "Premier commit sur feature/test"
```
---
4. Revenez sur la branche principale `main` :
```bash
git checkout main
```
5. Fusionnez la branche `feature/test` dans `main` :
```bash
git merge feature/test
```
6. Supprimez la branche fusionnée :
```bash
git branch -d feature/test
```
---
### Résolution de conflits
1. Créez deux branches et modifiez le même fichier dans les deux :
```bash
git branch feature/branch1
git branch feature/branch2
```
2. Apportez des modifications dans `feature/branch1` :
```bash
git checkout feature/branch1
echo "Modification sur branch1" >> fichier.txt
git add fichier.txt
git commit -m "Ajout depuis branch1"
```
---
3. Apportez des modifications dans `feature/branch2` :
```bash
git checkout feature/branch2
echo "Modification sur branch2" >> fichier.txt
git add fichier.txt
git commit -m "Ajout depuis branch2"
```
4. Essayez de fusionner `feature/branch1` dans `feature/branch2` :
```bash
git checkout feature/branch2
git merge feature/branch1
```
5. Résolvez le conflit dans le fichier concerné :
- Ouvrez le fichier contenant les délimitations `<<<<<<<`, `=======`, et `>>>>>>>`.
- Supprimez ces marqueurs et gardez la version souhaitée.
---
6. Ajoutez le fichier corrigé à la zone de staging :
```bash
git add fichier.txt
```
7. Terminez la fusion avec un commit :
```bash
git commit
```
8. Vérifiez l’état de votre dépôt :
```bash
git status
```
9. Poussez les modifications vers le dépôt distant si nécessaire :
```bash
git push origin feature/branch2
```
---
# Petit plus 🤪
| **Commande** | **Description** | **Nouveauté** | **Version Git** | **Équivalent/Remplaçant** |
|----------------------|----------------------------------------------------------------------------------------------------|---------------|-----------------|------------------------------------------|
| `git restore` | Restaure des fichiers (dans le répertoire de travail ou dans l'index). | Oui | 2.23 | `git checkout --` |
| `git switch` | Change de branche, remplaçant `git checkout` pour cette fonction. | Oui | 2.23 | `git checkout` |
| `git worktree` | Travaille sur plusieurs branches dans des répertoires distincts. | Non | 2.5 | - |
---
| **Commande** | **Description** | **Nouveauté** | **Version Git** | **Équivalent/Remplaçant** |
|----------------------|----------------------------------------------------------------------------------------------------|---------------|-----------------|------------------------------------------|
| `git rebase --onto` | Repositionne une branche sur une autre base différente. | Non | Depuis toujours | Partie de `git rebase` |
| `git diff --cached` | Montre les différences entre les fichiers indexés et le dernier commit. | Non | Depuis toujours | - |
| `git log --grep` | Recherche dans les messages de commit. | Non | Depuis toujours | - |
| `git reflog` | Affiche toutes les actions récentes, même celles supprimées des logs classiques. | Non | Depuis toujours | - |
---
| **Commande** | **Description** | **Nouveauté** | **Version Git** | **Équivalent/Remplaçant** |
|----------------------|----------------------------------------------------------------------------------------------------|---------------|-----------------|------------------------------------------|
| `git blame` | Identifie quel commit et auteur ont modifié chaque ligne d’un fichier. | Non | Depuis toujours | - |
| `git bisect` | Recherche le commit fautif en divisant l’historique en deux (recherche binaire). | Non | Depuis toujours | - |
| `git clean` | Supprime les fichiers non suivis dans le répertoire de travail. | Non | Depuis toujours | - |
---
| **Commande** | **Description** | **Nouveauté** | **Version Git** | **Équivalent/Remplaçant** |
|----------------------|----------------------------------------------------------------------------------------------------|---------------|-----------------|------------------------------------------|
| `git sparse-checkout`| Télécharge uniquement une partie du dépôt distant (utile pour les grands dépôts). | Oui | 2.25 | - |
| `git show` | Affiche les détails d’un commit spécifique, incluant les modifications. | Non | Depuis toujours | - |
---
# Mais encore ?? 🤯
Voici des exemples pratiques pour chaque commande, avec les équivalents lorsqu’elle en remplace une ancienne.
---
### 1. **git restore**
- **Description :** Restaure un fichier à son état dans le dernier commit ou retire de l'index.
- **Exemple :**
```bash
git restore fichier.txt # Restaure le fichier au dernier commit
git restore --staged fichier.txt # Retire le fichier de l'index
```
- **Equivalent (ancienne commande) :**
```bash
git checkout -- fichier.txt # Pour restaurer le fichier
```
---
### 2. **git switch**
- **Description :** Change de branche.
- **Exemple :**
```bash
git switch feature/test # Passe sur la branche feature/test
git switch -c nouvelle-branche # Crée et passe sur une nouvelle branche
```
- **Equivalent (ancienne commande) :**
```bash
git checkout feature/test # Pour changer de branche
```
---
### 3. **git worktree**
- **Description :** Travaille sur plusieurs branches dans des répertoires différents.
- **Exemple :**
```bash
git worktree add ../nouveau_dossier feature/test # Crée un répertoire pour travailler sur une branche
git worktree remove ../nouveau_dossier # Supprime le répertoire sans affecter la branche
```
---
### 4. **git rebase --onto**
- **Description :** Rebase une branche en changeant sa base.
- **Exemple :**
```bash
git rebase --onto nouvelle-base ancienne-base branche
# Rebase 'branche' pour qu'elle commence depuis 'nouvelle-base' au lieu de 'ancienne-base'
```
---
### 5. **git diff --cached**
- **Description :** Affiche les différences entre l’index (staging) et le dernier commit.
- **Exemple :**
```bash
git diff --cached # Affiche les modifications indexées prêtes à être commit
```
---
### 6. **git log --grep**
- **Description :** Recherche des messages spécifiques dans les commits.
- **Exemple :**
```bash
git log --grep="fix bug" # Recherche les commits contenant 'fix bug' dans leur message
```
---
### 7. **git reflog**
- **Description :** Montre les actions récentes dans le dépôt, même celles effacées du log classique.
- **Exemple :**
```bash
git reflog # Liste toutes les actions (checkout, commit, reset, etc.)
git reset --hard HEAD@{3} # Revenir au 3e état précédent
```
---
### 8. **git blame**
- **Description :** Affiche quel commit et auteur ont modifié chaque ligne d’un fichier.
- **Exemple :**
```bash
git blame fichier.txt # Affiche chaque ligne avec son auteur et commit correspondant
```
---
### 9. **git bisect**
- **Description :** Effectue une recherche binaire pour trouver un commit fautif.
- **Exemple :**
```bash
git bisect start
git bisect bad # Marque le commit actuel comme fautif
git bisect good <hash_commit> # Marque un commit sain
# Git vous guidera pour tester chaque commit
git bisect reset # Termine la recherche
```
---
### 10. **git clean**
- **Description :** Supprime les fichiers non suivis.
- **Exemple :**
```bash
git clean -fd # Supprime les fichiers (-f) et répertoires (-d) non suivis
git clean -n # Simule les suppressions sans les effectuer
```
---
### 11. **git sparse-checkout**
- **Description :** Télécharge uniquement une partie du dépôt.
- **Exemple :**
```bash
git sparse-checkout init # Active le mode sparse-checkout
git sparse-checkout set dossier/ # Télécharge uniquement le dossier spécifié
```
---
### 12. **git show**
- **Description :** Affiche les détails d’un commit.
- **Exemple :**
```bash
git show <hash_commit> # Affiche les changements et métadonnées d’un commit
git show HEAD # Affiche les détails du dernier commit
```
---
# Pour un cours *presque parfait* 🤓
Bon, on ne va pas se mentir, ce cours est déjà une pépite 💎. Mais, si je voulais vraiment viser l’excellence absolue (genre le genre de cours qui fait pleurer Linus Torvalds de fierté 🥹), voici ce que je pourrais encore ajouter :
---
### **1. Les hooks Git, ou comment automatiser vos bonnes habitudes 🪝**
Parce qu’on sait tous que personne n’a envie de faire manuellement des vérifications répétitives. Un `pre-commit` pour checker que le code ne casse pas tout ? Un `post-merge` pour envoyer un message Slack ? Ça, c’est la classe ultime.
> "Ah, je vous avais dit que Git pouvait aussi être votre assistant perso ?"
---
### **2. Le guide pour devenir le ninja des conflits 🥷**
Parce qu’avouons-le, résoudre un conflit Git, c’est parfois comme essayer de déchiffrer une énigme d’un escape game à l’aveugle. Avec `git mergetool` et des outils comme Meld, on passe en mode *easy* et ça devient presque un plaisir. Presque. 😉
---
### **3. Les workflows pour faire le tri dans vos branches comme Marie Kondo 🧹**
GitFlow, GitHub Flow, Trunk-Based Development… Pourquoi choisir quand on peut tout expliquer ? Et si vos branches ne "spark joy", il est peut-être temps de les nettoyer. Merci `git branch -d`.
---
### **4. Les alias Git pour les flemmards organisés 🤐**
Parce que taper `git checkout feature/superlongbranchname` à chaque fois, ça use. Alors qu’un petit alias `co`, c’est instantané. Du temps gagné pour les pauses café. ☕
---
### **5. Des astuces pour bosser avec des dépôts énormes (genre vraiment énormes 🦖)**
`git sparse-checkout` pour télécharger juste ce qu’il faut. Et si vous aimez collectionner des fichiers binaires de 1 Go, `git lfs` est votre meilleur ami. On ne juge pas.
---
### **6. Quand vous avez besoin de Sherlock Holmes dans votre historique 🔍**
`git blame` pour savoir QUI a cassé le code (avec diplomatie, bien sûr). Et si vous voulez un vrai détective, `git bisect` fait une recherche binaire pour identifier LE commit coupable. À ne pas utiliser si vous êtes perfectionniste, parce que oui, c'était VOUS.
---
### **7. Une dose d’humanité avec des anecdotes**
Vous saviez que Git a été créé par Linus Torvalds parce qu’il trouvait les autres outils *"nuls"* (je paraphrase) ? Eh bien voilà, de quoi briller en société lors de vos soirées DevOps. 🥂
---
### **8. Une FAQ pour calmer les crises existentielles 😱**
"Pourquoi Git me dit que tout va bien alors que rien ne marche ?" – Pas de panique, un petit `git status` pour respirer. Parce que Git, c’est aussi apprendre à gérer ses émotions.
---
En résumé, si vous cherchez la *perfection Git*... Vous venez de tomber sur le *cours ultime* (ou presque). Allez, à vos claviers, et que le commit soit avec vous. 😎
{"metaMigratedAt":"2023-06-17T00:32:13.318Z","metaMigratedFrom":"YAML","title":"Git","description":"Formation Git","robots":"noindex, nofollow","contributors":"[{\"id\":\"35198f6d-8c66-4636-8d98-b19eb0b4c48c\",\"add\":137118,\"del\":85124}]","lang":"fr-FR","slideOptions":"{\"fragments\":true,\"transition\":\"fade\",\"slideNumber\":true,\"previewLinks\":true,\"overview\":true,\"progress\":true,\"width\":1366,\"height\":768}","breaks":false}