git init, git status, git add, git commit, git log, git checkout, git tag
Dans cette partie, nous allons voir les concepts et les commandes de base : les dépôts, les commits, les branches. Lecture indispensable ! (ça devrait être enseigné dès le primaire)
Dépôt
git init, git status
Imaginons le projet avec l’arborescence suivante :
myproject/ └── toto.txt
Pour sauvegarder le contenu de dir, nous allons créer un dépôt (repository ou repo) git.
Nous obtenons l’arborescence suivante :
myproject/ => Arbre de travail ├── toto.txt └── .git => Dépôt
Toutes les informations de versionnement seront stockées le dossier .git
. Ce dossier est appelé dépôt. Il pourrait être stocké n’importe où.
Le dossier myproject
est l’arbre de travail. C’est dans ce dossier qu’on peut apporter des modifications à nos fichiers et les versionner.
Le fichier toto.txt
n’aura pas besoin de changer de nom.
TP Créer et initialiser son projet
Ouvrir un terminal
mkdir myproject # Créer le dossier
cd myproject # Aller dans le dossier
echo "bonjour" > toto.txt # Créer un fichier toto.txt
git init # Initialiser le projet en tant que dépôt
ls -a # Vérifier l'existence du dossier .git
# . .. .git toto.txt
git status # Afficher le statut de l'arbre de travail
Sortie :
Sur la branche main Aucun commit Fichiers non suivis: (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé) toto.txt aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez "git add" pour les suivre)
Pas génial, ya du rouge. La suite dans le TP suivant.
Commit (révision/version)
git add, git commit, git log
Le repo est initialisé, mais rien n’a encore été versionné dans le repo.
Dans git, une version/révision est appelée un commit.
Pour créer un commit, il y a deux étapes :
git add
a deux fonctions :- ajouter des nouveaux fichiers à l’index des fichiers suivis par git
- stocker les modifications dans une zone intermédiaire, la staging area (zone de transit) qui nous permet de faire de la vérification sur les fichiers qu’on intègre dans une révision.
git commit
: sauvegarde les modifications de tous les fichiers présents dans la staging area dans le dossier.git/
et produit un commit avec une clé SHA1.
┌────────────┐┌────────────┐┌──────────┐
│Working Tree││Staging Area││Local Repo│
└─────┬──────┘└─────┬──────┘└────┬─────┘
│ │ │
│ git add │ │
│────────────>│ │
│ │ │
│ │ git commit │
│ │───────────>│
│ │ │
│ git checkout/switch │
│<─────────────────────────│
│ │ │
│ git merge │
│<─────────────────────────│
Un fichier peut être référencé dans 3 zones : l’arbre de travail, la zone de transit et le dépôt.
Pour le versionnement, il devra passer par ces trois zones successivement.
A chaque fois que vous versionner grâce aux commandes git add
+ git commit
, vous créez un nouveau commit qui s’ajoute dans une chaîne, une lignée de commits.
┌────────┐
│commit C│ C hérite de B
└┬───────┘
┌▽───────┐
│commit B│ B hérite de A
└┬───────┘
┌▽───────┐
│commit A│
└────────┘
Exemple de graphe de lignée de commits. Le commit le plus récent est C, B est son commit parent. A est le commit le plus ancien.
Plus précisément, pour chaque commit, il se passe ceci :
- Git versionne sur l’intégralité de l’arbre de travail. Lors de la création d’un commit, git fait une photographie de l’instant en stockant les modifications apportées dans le projet dans le dossier
.git/
et en attribuant à cette photographie un identifiant cryptographique unique SHA1 (ex:338b0b72fefb35d6e374127768aed10642aada0b
, raccourci en 7 caractères338b0b7
) - Chaque commit est associé à un ou plusieurs commits parents ce qui nous permettra de retrouver l’historique.
🟢 Conseil :
C’est à vous de choisir à quel moment versionner votre travail. Il n’y a pas vraiment de convention. Considérez simplement un moment qui est un point de sauvegarde pour votre projet. Vous pouvez versionner autant que vous voulez, git est très robuste quant au nombre de commits.
TP Versionner son projet
git add toto.txt # Ajout à l'index et stockage des modifications dans la staging area
git commit -m "Mon premier commit" # Création d'un commit avec un message
git log # Visualisation de l'historique de commits
Sortie :
commit 34c9d3c50746bf01df0e3e7a9ec9c59f2803aa17 (HEAD -> main) Author: Léo Le Lonquer <leo.le.lonquer@bidulon.fr> Date: Thu Apr 4 09:50:48 2024 +0200 Mon premier commit
Amusez-vous à modifier le fichier toto.txt
, à le versionner, à vérifier l’état de votre repo avec git status
et à regarder les logs avec git log
.
Branches et arborescence 🌿
Branchage et merge
git branch, git switch, git merge
Pour l’instant nous étions sur un repo très simple. Imaginons que nous voulons ajouter une fonctionnalité sans casser l’état actuel de notre projet. Nous pouvons créer une branche qui permettra de travailler à côté sur cette nouvelle fonctionnalité tranquillement.
- Nous pouvons créer autant de branches que souhaitées, à partir de n’importe quelle branche. Vous allez donc créer une arborescence, qui s’apparente à un arbre généalogique.
- Par défaut, nous sommes la branche principale
main
(master
pour des projets plus anciens).
E---F---G topic
/
A---B---C---D main
Graphe d’un repo présentant une branche topic
issue de la branche main
Une fois que les fonctionnalités sont développées et matures, nous pouvons ramener les modifications d’une branche dans une autre. C’est ce qu’on appelle un merge.
E---F---G topic
/ \
A---B---C---D---H main
Exemple de graphe après un merge
TP 1 Créer une branche, basculer dessus et observer les effets du basculement
Toujours avec le même projet
git branch topic # Créer la branche à partir du dernier commit
git switch topic # changer de branche
# Ou les deux commandes en une
git switch -c topic
git branch # Afficher les branches existantes
# main
# * topic
Vous ne verrez pas de différences au premier abord. Ajoutons un fichier et versionnons l’état.
echo "coucou" > tutu.py # Créer un nouveau fichier
git add . && git commit -m "Premier commit de la branche topic"
ls
# toto.txt tutu.py
Une fois commité revenons à main.
git switch main
ls # Où est passé le fichier `tutu.py` ?
# toto.txt
git log
Vous ne verrez pas le commit avec le message “Premier commit de la branche topic” car vous êtes sur la branche main
qui n’a pas encore intégré les modifications faites sur topic
(heureusement !).
Rassurez-vous le fichier tutu.py
n’est pas perdu, il est simplement dans le dossier .git/
et attend que vous reveniez le voir. Git s’est chargé de modifier votre espace de travail courant pour revenir à un espace de travail correspondant à une autre branche.
git switch topic # Revenons à la branche topic
ls # Le fichier tutu.py réapparaît
# toto.txt tutu.py
TP 2 Faire un merge
Maintenant imaginons que nous avons terminé le développement de notre fonctionnalité, nous voulons réintégrer les développement dans la branche principale.
Le graphe de commit est dans l’état suivant :
B topic
/
0---A main
Exécutons le merge
git switch main
git merge topic --no-ff # l'option --no-ff est pour la cosmétique du graphe de commits, elle n'est pas utilisée usuellement
ls # tutu.py est présent
git crée un nouveau commit appelé merge commit pour signaler que vous avez intégré les modifications du dernier commit de la branche topic.
Le graphe de commits se retrouve dans l’état suivant :
B topic
/ \
0---A---C main
Les références (branche-HEAD-tag)
git log –graph, git checkout, git tag
Les références sont des pointeurs qui identifient un commit dans un graphe de commits. Il existe trois types de référence :
- HEAD : c’est la référence au dernier commit. A chaque commit, il est mis à jour. Il peut avoir deux états :
- attaché : il pointe vers une branche qui elle-même pointe vers un commit
- détaché : il ne pointe vers aucune branche, mais vers n’importe quel commit du graphe
- les branches : les branches ne sont en réalité que des pointeurs. Elles identifient un dernier commit d’une chaîne de commits. L’héritage se fait de proche en proche (rappelez-vous les commits stockent leur commit parent.). Si HEAD est associé à la branche, alors la référence de la branche est mise à jour lors d’un commit.
- tag : référence immutable (qui n’est jamais mis à jour) permettant de labeliser des commits plus importants que d’autres (ex : une version livrable du projet).
┌────────────────────────┐
│commit W (topic <= HEAD)│
└┬───────────────────────┘
┌─────────────────▽┐
│commit X (main) │
└┬─────────────────┘
┌▽───────┐
│commit Y│
└┬───────┘
┌▽───────┐
│commit Z│
└────────┘
Exemple de graphe et des pointeurs
TP Se balader dans le graphe des commits
Vous pouvez afficher le graphe de commits ainsi que l’état des pointeurs
git log --oneline --decorate --all --graph
Sortie :
* 316d42d (HEAD -> main) Merge branch 'topic' |\ | * f6c8d25 (topic) Premier commit de la branche topic |/ * 65b6302 Mon premier commit
Nous observons le graphe résultant du merge précédent.
Déplaçons nous dans un commit :
git checkout 65b6302
ls
# toto.txt
Réexaminons la carte :
# Revoir la carte et regarder où est placé le point HEAD
git log --oneline --decorate --all --graph
Sortie :
* 316d42d (main) Merge branch 'topic' |\ | * f6c8d25 (topic) Premier commit de la branche topic |/ * 65b6302 (HEAD) Mon premier commit
Nous observons que le pointeur HEAD
s’est déplacé sur le commit 65b6302
. Nous retrouvons uniquement les fichiers qui correspondent à ce commit.
Replaçons HEAD à son pointage précédent
git checkout -
git log --oneline --decorate --all --graph
Nous retrouvons le premier graphe.
Convention de nommage de branche
Les branches peuvent être utilisées et nommées très librement. Cependant quelques conventions ont été créées pour que les développeurs retrouvent leurs marques entre différents projets. Je vous présente ici la nomenclature git-flow :
- la branche
main
oumaster
: c’est la branche principale, de référence, qui reproduit la production. Elle doit toujours être fonctionnelle. - la branche
dev
oudevelop
: c’est la branche de développement, celle qui va proposer une nouvelle version d’un logiciel et dans laquelle on va merger toutes les features. feature
: ce sont les branches d’ajout de fonctionnalités. Elles sont nommées généralementfeature/[ma_fonctionnalite]
(ex :feature/add_refresh_button
). Dans certaines organisations, on référence le numéro de ticket correspondant à la feature (ex:feature/DTL-92_add_refresh_button
voire même simplementfeature/DTL-92
)hotfix
: pour corriger un bug dans la branche de productionmain
et la reporter dansdev
Pour des développements simples, si vous êtes le seul contributeur, vous pouvez utiliser seulement main
ou main
et dev
par exemple.
Vous pouvez aussi bien sûr créer votre propre convention, faites en sorte qu’elle soit la plus collective possible ! Et rappelez-vous que le principal c’est de rester branché 😎.
Bonnes pratiques sur les branches
De manière générale :
- une personne par branche (créer une autre branche à partir d’une autre si besoin)
- une branche par sujet : ajout/modification d’une configuration, ajout/modification d’une fonctionnalité
- Résoudre les merge conflicts dans une branche plutôt que dans la branche principale (ramener dans la branche les modifs de la branche principale avec
git merge
, expliqué plus bas). - Utiliser
git merge
et nongit rebase
Fichiers spéciaux
Le fichier .gitignore
Le fichier .gitignore
permet d’éviter l’indexation de certains documents sur le critère de patterns. Il se trouve à la racine de l’arbre de travail. On peut ignorer :
- des fichiers spécifiques
- des patterns de fichiers
- des dossiers
Exemple de fichier .gitignore
:
# Ignorer les fichiers de configuration de l'environnement de développement
.idea/
.vscode/
.classpath
.project
# Ignorer les fichiers de sauvegarde temporaires vim
*~
*.swp
# Ignorer les fichiers de logs
*.log
# Ignorer certains dossiers
lib/
var/
tmp/
tdsConfigGen/
Une fois que notre fichier est bien configuré, on peut indexer et commiter plus rapidement sans se soucier de l’indexation de fichiers inutiles :
git add . && git commit -m "Mon message"
Vous pouvez demander à ChatGPT ou MistralAI (pour défendre une solution française et open-source) de vous fournir un fichier .gitignore
en précisant le langage, les librairies, les modules, le IDE utilisées.
Le fichier .gitattributes
Si vous avez des problème de fin de lignes, car un des contributeurs.rices du projet est sur Linux quand l’autre est sur Windows, alors ajouter le fichier .gitattributes
à votre projet avec le contenu suivant :
# Adaptation automatique aux fins de ligne Windows ou Linux
* text=auto
Voir également cet exemple de fichier .gitattributes
généré par Codestral.
La suite
La suite ici : Git - 2 - Actions fréquentes
Ressources
- Présentation animée des principales commandes git : CS Visualized: Useful Git Commands
- Codes de triche Git : Gitlab Cheatsheet
- Lien vers la doc
.gitignore