Git

Git est un système de contrôle de version. Créez, gérez, fusionnez des branches. Indexez, commit, gérez l'historique et gérez dépôts distants.

Informations

Date de publication :

Date de modification :

Catégories : git

Auteur : Photo de profil de l'auteur de la documentation meezyr

Bannière documentation Git

Git est un système de contrôle de version (VCS = Version Control System) qui permet à une équipe de gérer les changements apportés à un système de fichiers, généralement du code. Chaque version comporte l'ensemble des modifications depuis la version précédente, et toutes les modifications des fichiers (ajout, suppression, modifications) sont enregistrées dans une base de données spécifique appelée dépôt (ou repository en anglais). 

La gestion de version décentralisée offre à chaque développeur la possibilité de stocker localement le projet avec son propre logiciel de gestion de versions. Créé en 2005 par Linus Torvald, Git fonctionne comme un système de fichiers préservant l'historique des fichiers d'un dossier spécifique. Il identifie de manière unique les fichiers, répertoires et sauvegardes en utilisant des hachages. Ces hachages transforment de manière irréversible les valeurs (telles que le contenu d'un fichier) en chaînes de caractères appelées "hash". Lorsqu'un fichier n'est pas modifié, son hash, ou somme de contrôle, reste inchangé et le fichier n'est pas réenregistré. Pendant les sauvegardes, Git enregistre uniquement les fichiers modifiés et crée des références pour les fichiers inchangés, optimisant ainsi le stockage des données.

1. Fonctionnement de base

1.1 Création d'un dépôt Git

Pour commencer à utiliser Git, vous devez initialiser un nouveau dépôt Git dans votre projet en utilisant la commande suivante :

git init

1.2 Configuration de Git

Vous pouvez configurer Git en utilisant la commande git config. Vous avez plusieurs options pour la configuration :

  • Configuration locale, sans option, si vous lancez la commande dans un répertoire Git, alors les configurations sont valable uniquement pour le dépôt en cours. La configuration se trouvera alors dans le dossier du dépôt dans .git/config :

git config user.name "Votre nom"
git config user.email "Votre adresse e-mail"
  • Configuration globale, avec l'option --global, si vous ajoutez cette option à la commande, alors la configuration se fera pour votre utilisateur sur votre machine. Le fichier de configuration se trouvera alors dans ~/.gitconfig (ou C:\Documents puis Settings\utilisateur ou C:\Users\utilisateur sur Windows) :

git config --global user.name "Votre nom"
git config --global user.email "Votre adresse e-mail"
  • Configuration système, avec l'option --system, si vous utilisez cette option, alors la configuration sera valable pour tous les utilisateurs du système. Le fichier de configuration se trouvera alors dans /etc/gitconfig (ou sur Windows dans C:\ProgramData\Git\config) :

git config --system user.name "Votre nom"
git config --system user.email "Votre adresse e-mail"

Pour afficher la configuration de Git, vous pouvez utiliser la commande suivante :

git config --list

Pour mettre en cache les identifiants, vous devez utiliser la commande suivante :

git config --global credential.helper cache --timeout nombre-de-secondes

Pour vider le cache cette commande doit être utilisé :

git credential-cache exit

Pour automatiquement rebase lors des git pull, on peut utiliser cette commande :

git config --global pull.rebase true

1.3 Indexation de fichiers

La commande git status permet d'obtenir certaines informations sur les fichiers qui ont été indexés.

Pour suivre les modifications de vos fichiers avec Git, vous devez les indexer en utilisant la commande git add, cela permet en fait d'ajouter la version actuelle d'un fichier à la prochaine sauvegarde. Par exemple, pour indexer un fichier ou un dossier spécifique, utilisez :

git add nom-du-fichier-ou-dossier

1.4 Ignorer des fichiers

Pour ignorer des fichiers que vous ne souhaitez pas inclure dans Git, créez un fichier .gitignore à la racine de votre projet et ajoutez les noms de fichiers ou de dossiers à ignorer. Dans ce fichier vous mettrez souvent le dossier des dépendances node_modules, les fichiers de configuration de votre éditeur de code, des fichiers de log en local, ce qui ne doit pas être visible par tous et autres. Vous pouvez utiliser des expressions régulières simplifiées dans ce fichier pour ignorer certains types de fichiers :

  • * signifie un ou plusieurs caractères
  • ** signifie une série d'un ou plusieurs dossiers

Consultez la documentation officielle sur gitignore pour en savoir plus.

1.5 Informations et différences

La commande git diff permet d'obtenir plus d'informations sur les fichiers indexés en zone de transit (staging area). Cette commande sans aucune option permet d'afficher les modifications des fichiers dans le répertoire de travail qui ont été modifiés mais non indexés. La commande git diff --staged permet d'afficher les modifications des fichiers indexés par rapport à la dernière sauvegarde.

1.6 Sauvegardes (Commits)

Un commit est une sauvegarde dans Git, cela signifie littéralement qu'on engage les modifications indexées. Une sauvegarde est à tout jamais dans le dépôt Git. Pour effectuer un commit avec un message de validation, utilisez la commande suivante :

git commit -m "Votre message de validation"

La commande avec l'option -a permet de faire un commit sans indexer manuellement les modifications :

git commit -a -m "Votre message de validation"

L'option --amend permet d'ajouter des fichiers que vous avez oublié et de modifier le message de validation (--no-edit pour pas modifier le message) d'un commit.

1.7 Historique

Vous pouvez visualiser l'historique des commits en utilisant la commande git log, affiche les commits du plus récent au plus anciens. Pour afficher les différences avec le commit précédent, utilisez git log -p. Pour obtenir un résumé des modifications effectuées pour chaque commit par rapport au commit précédent, utilisez git log --stat.

1.8 Suppression

La commande git rm nom-du-fichier permet de supprimer un fichier dans Git. L'option --cached fichier permet de supprimer le fichier de l'index (unstaged), mais restera dans le répertoire de travail.

1.9 Traçabilité

La commande git blame nom-du-fichier permet d'indiquer pour chaque ligne d'un fichier quelle personne l'a modifié et à quelle date.

2. Gestion des branches

Une branche est simplement un pointeur, également appelé référence, vers un commit. La branche principale qui est créée par défaut par Git lors du git init est master. HEAD est une référence, ou pointeur, vers le commit, la branche, ou le tag sur laquelle vous vous trouvez actuellement. Autrement dit elle pointe toujours directement, ou indirectement, vers un commit. Les branches sont une des fonctionnalités principales de Git, elles n'ont aucun coût d'espace mémoire, il s'agit simplement d'un pointeur sur un commit et elles sont très recommandées.

2.1 Création de branches

Git permet de travailler sur différentes branches. Pour créer une nouvelle branche, utilisez la commande suivante :

git branch nom-de-branche

L'option -m permet de modifier le nom d'une branche :

git branch -m "nouveau-nom"

L'option -d permet de supprimer une branche ou alors l'option -D pour forcer la suppression :

git branch -d nom-de-branche
git branch -D nom-de-branche

2.2 Changement de branche

Cette commande permet de naviguer dans HEAD et permet de déplacer HEAD où vous souhaitez. Pour basculer sur une autre branche, utilisez la commande git checkout :

git checkout nom-de-branche

Pour ce déplacer à un commit précis, on peut utiliser git checkout hash-commit permet de déplacer HEAD vers le commit spécifié et de mettre à jour le répertoire de travail et l'index à la version correspondant à ce commit.

2.3 Fusion de branches

Pour fusionner deux branches sans modifications de l'histoire, utilisez la commande git merge :

git merge nom-de-branche

Si la branche master n'a pas de commit en plus par rapport à la branche fusionnée dans celle-ci on appelle cela une fusion fast-forward car aucun commit de fusion n'est créé.

Dans la situation où il y a des commits divergents entre les branches auth et master. Git ne peut donc pas simplement déplacer la branche master sur le commit pointé par la branche auth comme dans le cas d'une fusion fast-forward.

La commande git merge --squash branche-fix permet de rassembler plusieurs commits en un seul commit lors d'une fusion de branche.

2.4 Manipulation de branches

Voici différentes commandes utiles pour la gestion de branches :

  • git clean -i : permet de supprimer tous les fichiers non suivis du répertoire de travail, sauf ceux contenus dans le fichier .gitignore.
  • git revert hash-commit : permet de créer un nouveau commit qui va annuler tous les changements effectués par le commit spécifié.
  • git revert --no-commit hash-commit : permet d'annuler les changements d'un commit sans créer de nouveau commit.
  • git reset nom-du-fichier : permet de désindexer un fichier en conservant les changements dans le répertoire de travail (l'inverse de la commande git add -nom-du-fichier).
  • git reset commit : permet de déplacer la branche sur laquelle pointe HEAD sur le commit sélectionné.

2.5 Résolution de conflits

En cas de conflits de fusion (ou merge conflicts), ce sont des modifications conflictuelles sur des mêmes fichiers, vous devrez résoudre manuellement les conflits dans les fichiers concernés, puis effectuer un commit pour finaliser la fusion.

3. Opérations avancées

3.1 Push

La commande git push permet de mettre à jour les références sur le dépôt distant. Par défaut, c'est la branche sur laquelle est positionnée HEAD qui est push vers la branche distante correspondante. La commande git push --delete nom-de-branche permet de supprimer une branche distante.

La commande git push origin --tags permet de push tout les tags d'un coup.

3.2 Rebase

La commande git rebase nom-de-branche permet de prendre tous les changements de chaque commit sur une branche et de les appliquer les uns après les autres à la fin d'une autre branche, c'est donc une fusion de deux branches mais avec modification de l'histoire. Il ne faut jamais rebaser des commits qui ont déjà été push, il ne faut jamais modifier l'historique si il a été envoyé sur le répertoire distant ou alors dont vous êtes certain à 100% sûr que personne d'autre n'a travaillé dessus.

La commande git rebase -i HEAD~3 permet de faire un rebasage interactif qui modifie plusieurs commits qui se suivent.

3.3 Fetch

La commande git fetch met à jour localement les branches distantes. En détails, git fetch va télécharger les pointeurs des branches et des tags distants ainsi que tous les objets (commits, blobs et arbres) nécessaires. Elle est seulement une mise à jour des branches locales, aucun changement ne sera appliqué ni à votre répertoire de travail, ni à votre index, ni à votre historique local. L'option --prune permet de supprimer les branches de suivi inutiles.

3.4 Pull

La commande git pull est le raccourci de deux commandes git fetch puis git merge.

3.5 Clonage de dépôts distants

Pour cloner un dépôt distant, utilisez la commande git clone :

git clone URL-du-dépôt

On peut utiliser la commande git clone en SSH mais il faut enregistrer une clé SSH, pour cela il faut utiliser la commande ssh-keygen.

3.6 Travailler avec des dépôts distants

Vous pouvez ajouter des dépôts distants, les lister, les renommer localement ou les supprimer en utilisant les commandes git remote :

git remote add origin URL-ou-SSH
git remote -v
git remote rename ancien-nom nouveau-nom
git remote rm nom-répertoire

3.7 Stash

La commande git stash permet d'enregistrer les modifications présentes dans votre répertoire de travail et votre index pour les réappliquer plus tard. L'option -u permet de sauvegarder temporairement les fichiers non suivis par Git.

La commande git stash apply stash@{1} permet de restaurer les changements de la sauvegarde temporaire et la commande git stash drop stash@{1} permet de supprimer un stash.

3.8 Commandes avancées

  • git reflog : permet de retrouver l'historique des références qui ont été pointées par HEAD et par vos branches (utile lors de suppressions). Le ReFlog est uniquement local, cela signifie que ce sont les déplacements que vous avez fait localement uniquement.
  • git prune : permet de supprimer les objets orphelins de Git.
  • git gc : permet de procéder au nettoyage et à l'optimisation de sa base de données locale Git (gc pour garbage collection).
  • git tag "nom-du-tag" : permet de créer des tags, les tags sont des marqueurs pour des versions importantes. Ils sont également appelés étiquettes.
  • git tag -a v1.0.1 -m "nom-du-tag" : permet de créer des tags annoté, les tags annotés sont des objets Git contenant des informations supplémentaires.
  • git cherry-pick : permet de sélectionner un commit par référence et de l'appliquer sur la branche pointée par HEAD.

3.9 Gestion des fichiers volumineux (Git LFS)

Git LFS (Large File Storage) est une extension open source de Git qui permet de gérer des fichiers volumineux. Il est utile pour stocker des fichiers binaires tels que des images ou des vidéos.

4. Bonnes pratiques Git

4.1 Flow Git

Un flow Git est un ensemble de règles qu'une équipe s'impose sur un projet pour une gestion optimale d'un projet.

Le Flow Git standard comprend généralement une branche principale master pour la production et une branche develop pour le développement.

4.2 GitFlow

GitFlow est un flow plus exigeant qui est utile pour les projets importants. Il comprend plusieurs branches telles que master, develop, hotfix, release, et feature.

Il existe une librairie permettant de générer les actions Git à effectuer pour suivre le GitFlow de manière beaucoup plus rapide. Sur MacOS, il suffit de faire brew install git-flow-avh. Sur Linux / Windows (sur Git Bash), faites sudo apt-get install git-flow, plus d'informations sur la documentation.

4.3 Hook

Un hook en programmation permet d'exécuter du code à un moment précis lorsque certains événements surviennent. Par défaut, Git place quelques scripts mais qui ne sont pas activés dans .git/hooks. Un hook pre-commit s'exécute avant d'effectuer le commit, avant même l'ouverture de l'éditeur de texte pour le message de validation si vous n'utilisez pas l'option -m. Son objectif est d'empêcher d'effectuer un commit contenant un console.log :

#!/bin/bash
exec < /dev/tty
if test $(git diff --cached | grep ^+.*console.log | wc -l) != 0
then
    read -p "Au moins un console.log est ajouté dans votre commit ! Êtes-vous certain de continuer ? [o/n]: " choix
    if [[ $choix == 'o' || $choix == 'O' ]]
    then
       exit 0;
    else
        exit 1;
    fi
fi

La librairie husky permet d'utiliser tous les hooks Git très facilement, pour cela il suffit d'installer Node.js et d'initialiser npm et Git (npm init -y puis git init).

La librairie commitlint force l'utilisation de conventions pour la rédaction des messages de validation pour les commits.

Vous pouvez utiliser un hook afin de reformater le code systématiquement avant un commit, il s'appel Prettier.

4.4 Utilisation d'alias

Les alias sont utilisés partout en programmation. Ils permettent simplement de créer des raccourcis pour une ou plusieurs commandes. Git possède également son système d'alias et vous pouvez donc écrire facilement tous les raccourcis que vous souhaitez pour vos commandes Git. Vous pouvez créer des alias Git pour simplifier vos commandes, par exemple :

git config --global alias.raccourci commande
git config --global alias.ci commit
git config --global alias.st status