Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Git
  3. Consultation et manipulation de l’historique
Extrait - Git Maîtrisez la gestion de vos versions (concepts, utilisation et cas pratiques) (4e édition)
Extraits du livre
Git Maîtrisez la gestion de vos versions (concepts, utilisation et cas pratiques) (4e édition) Revenir à la page d'achat du livre

Consultation et manipulation de l’historique

Lister les commits avec git log

L’une des fonctionnalités les plus importantes d’un VCS est de retrouver rapidement un certain nombre d’informations, par exemple les modifications qui ont été effectuées depuis une date précise ou encore les modifications en cours dans le répertoire de travail.

La commande git log va nous permettre d’afficher beaucoup d’informations sur les commits. Cette commande est très puissante et possède de nombreuses options. Il suffit de consulter l’aide de cette commande pour mesurer les possibilités qu’elle offre.

Par défaut, git log affiche la liste des commits du dépôt en ordre chronologique décroissant. La sortie peut être très importante (voire monstrueuse selon la taille du projet) car tous les commits effectués pendant toute la vie du dépôt sont affichés.

Pour tester les commandes permettant de naviguer dans un dépôt facilement sans devoir créer un dépôt et y ajouter beaucoup de contenu, il peut être opportun de cloner un dépôt accessible sur GitHub. La commande suivante va télécharger le dépôt du framework web Django et le placer dans le dossier django :

git clone https://github.com/django/django.git 

Cette commande sera expliquée plus en détail dans le chapitre Partager un dépôt, à la section Cloner un dépôt distant. Pour faire simple, cette commande ne va pas uniquement télécharger le code, mais tout le dépôt avec tout l’historique et donc avec tous les commits.

La commande nous affiche une sortie nous confirmant la bonne exécution du clone :

Cloning into 'django'... 
remote: Counting objects: 324353, done. 
remote: Compressing objects: 100% (4/4), done. ...

Afficher les différences de contenu

Il est intéressant d’être en mesure de récupérer des commits, mais parfois ce que le développeur cherche se trouve dans le contenu même des modifications ajoutées par le commit, le répertoire de travail ou encore l’index. Pour cela, il doit utiliser la commande git diff.

La commande git diff affiche une liste des ajouts et des suppressions de lignes entre deux commits ou alors entre les différentes zones (répertoire de travail, index).

Pour que les exemples prennent du sens, il faut modifier au moins un fichier du dépôt. Les données avec lesquelles le fichier sera modifié ne sont pas importantes, elles serviront juste à l’affichage des exemples. Dans le cas du dépôt de Django, il est possible de modifier le fichier README.rst pour y ajouter une ligne à la fin (ligne d’exemple à ajouter : Je teste la commande git diff). Il faut ajouter ensuite cette modification à l’index.

git add README.rst 

Il faut remodifier ce fichier en modifiant cette dernière ligne (ligne d’exemple : Je teste la commande diff de git).

1. Différences en cours dans le répertoire

L’un des cas où git diff est très utilisé est celui où le développeur veut visualiser les modifications présentes dans son répertoire de travail par rapport à son index. Prendre connaissance de ces modifications lui permet de ne pas ajouter dans l’index celles qu’il ne souhaite pas. Pour afficher les différences entre le répertoire de travail et l’index, il faut utiliser la commande suivante :

git diff 

Cette commande affiche la sortie suivante :

diff --git a/README.rst b/README.rst 
index 6e9bc5f..9f4dcc9 100644 
--- a/README.rst 
+++ b/README.rst ...

Identifier l’auteur d’une ligne de code

Lorsqu’un développeur travaille sur un code, il peut parfois se demander lequel de ses collègues a retravaillé sur le code en question ou lequel a modifié en dernier une ligne particulière. Le fait de savoir qui a modifié une ligne permettra de savoir qui interroger pour avoir plus de détails concernant la partie sur laquelle le développeur travaille.

Par exemple, il arrive très régulièrement de se demander quand, par qui et pourquoi une ligne de code a été ajoutée ou modifiée dans un fichier. Toutes ces informations sont centralisées dans le commit, la seule complication étant de retrouver le commit ayant modifié cette ligne particulière.

Pour utiliser git blame sur un fichier, il faut utiliser la syntaxe suivante :

git blame nom_fichier 

Par exemple, en prenant le fichier README.rst de Django il faut utiliser la commande suivante :

git blame README.rst 

Cette commande affiche la sortie suivante tronquée (les deux premières lignes sont affichées) :

b2cb66bf README   (Adrian Holovaty  2005-07-21 01:37:28 +0000  ==> Ligne 
226acf35 README   (Adrian Holovaty  2012-04-27 22:25:08 -0500  ==> Ligne 

La sortie précédente est tronquée car elle n’était pas très lisible. Les textes ==> Ligne remplacent en réalité les deux premières lignes du fichier README.rst. Comme la capture le laisse supposer, la capture de git blame va afficher toutes les lignes du fichier avec les informations suivantes avant chacune d’entre elles :

  • Le hash du commit qui a introduit ou modifié la ligne.

  • Le fichier dans lequel la ligne a été introduite ou modifiée (dans cet exemple, le fichier README.rst...

Rechercher des commits avec le mode pick axe

Le mode pick axe ne correspond pas à une commande de Git, car c’est en réalité un mode utilisable avec plusieurs commandes de Git en ajoutant un argument. Le mode pick axe va permettre de rechercher les commits en fonction des modifications qu’ils ajoutent. C’est-à-dire que l’option pick axe va permettre de savoir dans quels commits le contenu spécifié a été ajouté ou supprimé.

Le mode pick axe peut être utilisé avec git log, mais aussi avec git diff ou encore avec la commande git format-patch. Pour utiliser cette fonctionnalité, il faut rajouter l’argument -S suivi du mot ou de la chaîne à rechercher :

git log -S "chaîne à rechercher" 

Par exemple, pour rechercher les commits du projet Django ajoutant ou supprimant la chaîne « Web framework that » il faut utiliser la commande suivante :

git log -S "Web framework that" 

Cette commande trouve quatre commits qui ajoutent ou suppriment la chaîne recherchée.

Cette commande permet alors d’effectuer des recherches beaucoup plus précises, directement dans les lignes modifiées ou ajoutées. Il existe également le paramètre -G qui permet de rechercher les commits à partir de leurs modifications en fonction d’une expression régulière. Par exemple, pour rechercher les commits ajoutant ou supprimant des lignes correspondant à l’expression régulière « Web framework.{0, 20}that », il faut utiliser la commande suivante :

git log -G "Web framework.{0, 20}that" 

Cette commande trouve un commit de plus que la commande utilisée avec l’argument -S. En effet, la dernière commande est plus permissive...

Supprimer les modifications du répertoire de travail

Il arrive régulièrement que lors d’un test ou d’un nouveau développement le développeur souhaite revenir à l’état de la dernière version du dépôt (pointée par HEAD). Cela se produit fréquemment lorsque, pendant les tests, le développeur modifie de nombreux fichiers, en ajoute quelques-uns dans l’index et laisse ces modifications sans les commiter. À la fin, il se rend compte qu’aucune modification ne doit être commitée et décide donc de supprimer ses modifications en revenant à l’état de HEAD.

Pour cela, il doit utiliser la commande suivante :

git reset --hard HEAD 

Attention : cette commande supprime toutes les modifications du répertoire de travail et de l’index. Cette commande est irréversible, elle doit donc être utilisée avec beaucoup de prudence.

Lorsqu’aucune modification n’a été ajoutée à l’index ou que celle-ci doit être conservée dans l’index, il convient d’utiliser la commande git checkout qui permet d’appliquer la version de l’index sur les fichiers du répertoire de travail. 

La syntaxe à utiliser est la suivante :

git checkout --  fichiers 

Apparue avec la version 2.24 de Git, la commande git restore permet également de restaurer l’état de fichiers du répertoire de travail à partir de l’index. Pour cela, il faut utiliser la syntaxe suivante :

git restore fichier 

Pour restaurer l’état du fichier à partir de HEAD, il faut utiliser git restore avec l’argument --staged.

Supprimer les modifications de l’index

Lorsque les modifications dans l’index ne présentent plus d’intérêt et doivent être supprimées (ou désindexées), il faut utiliser la commande suivante :

git reset HEAD 

Sans l’argument --hard, cette commande ne va pas modifier le répertoire de travail. Cette commande va juste remettre l’index dans le même état que la version la plus récente du dépôt. Les modifications présentes dans l’index seront supprimées de manière irréversible !

Revenir à un état antérieur

Plusieurs raisons peuvent nécessiter de se repositionner sur une version antérieure. L’une d’elles est de tester une version antérieure pour comparer certaines fonctions du logiciel. Il arrive également que les développeurs veuillent tester une ancienne version avant d’utiliser git bisect. La commande git bisect est un outil de recherche dichotomique dans le dépôt. Cette fonctionnalité est abordée dans le chapitre Les outils de Git, à la section Retrouver un commit erroné.

Pour revenir à un état antérieur en utilisant le hash du commit sur lequel le développeur veut se replacer, il faut utiliser la syntaxe suivante :

git reset hash_du_commit 

Par exemple, si le développeur désire revenir au projet tel qu’il l’était à la fin de l’année 2014, il recherche tout d’abord les commits effectués avant le 31 décembre 2014 :

git log --before="2014-12-31" -1 

Cette commande affiche la sortie suivante :

commit 013c2d8 
Author: Russell Keith-Magee <russell@keith-magee.com> 
Date:   Wed Dec 31 13:21:32 2014 +0800 
 
    Renamed variables to avoid name collision with import of 
django.db.models. 

Puis il utilise ensuite la commande git reset de cette manière :

git reset 013c2d8 

Celle-ci affiche alors la sortie suivante indiquant tous les fichiers modifiés depuis le commit visé (la sortie a été tronquée) :

Unstaged changes after reset: 
M   .gitattributes 
M   .gitignore 

En effet, le répertoire de travail n’a pas été modifié, il contient donc les modifications incluses dans le précédent commit où se trouvait...

Modifier le dernier commit

Lorsqu’on suit les versions d’un logiciel, il est normalement rare de vouloir modifier l’historique, mais il arrive malgré tout des moments où un développeur se rend compte qu’il a commité un peu trop vite.

Pour pouvoir modifier le dernier commit, il faut tout d’abord avoir rempli un impératif : le commit ne doit pas avoir été pushé (envoyé) sur un dépôt distant (pour plus de détails sur les dépôts distants, il convient de se référer au chapitre Partager un dépôt). En effet, si le commit précipité a été pushé et que le développeur le modifie, son identifiant (sous forme de hash) sera différent de celui du serveur et l’ancien commit aura disparu. Le serveur ne pourra pas savoir ce qui se sera réellement passé. En revanche, si le commit n’a pas été envoyé sur un dépôt distant, il est possible de corriger les erreurs sans problème.

Il arrive à chaque développeur, à un moment ou à un autre, de se précipiter pour commiter une modification. Plein de confiance, le développeur commite ses modifications avant de se rendre compte qu’il a laissé de nombreuses lignes de debug dans le code.

Il veut donc modifier le contenu de son dernier commit ainsi que le message de commit qui n’était pas clair du tout.

Pour cela, il doit utiliser la commande suivante :

git commit --amend 

Expliquer le fonctionnement de l’option --amend de git commit est plus simple avec un exemple : il faut imaginer un développeur qui crée un nouveau dossier, y initialise un dépôt, et ajoute un commit avec des modifications dans un fichier :

mkdir commitamend  
cd commitamend  
git init  ...

Afficher un résumé des commits

Git propose la commande shortlog permettant d’afficher un résumé des commits. Cette commande peut être intéressante dans de nombreux cas :

  • Afficher une liste des messages de commits pour une période donnée.

  • Afficher une liste des messages de commits pour des branches spécifiques.

  • Afficher une liste des messages de commits pour des tags spécifiques.

  • Afficher le nombre de commits par développeur.

Dans le cadre d’un projet répondant aux normes Git-Flow (méthode détaillée tout le long du chapitre Git-Flow : workflow d’entreprise) et SemVer (méthode détaillée au chapitre Les branches et les tags dans la partie Les tags), il est par exemple possible de visualiser tous les correctifs effectués pour la version 1.12. Un cas d’utilisation récurrent de la commande git shortlog est la génération de changelog.

Pour les projets comprenant de nombreux commits, la commande git shortlog utilisée sans argument est trop verbeuse et manque d’intérêt. En revanche, dans le cas d’un petit projet (comme celui du chapitre Scénario d’équipe) la commande git shortlog peut être représentative des incréments au projet de chaque développeur :

Benoit (3): 
     C7 : Branche task_type 
     C10 : Type task + admin 
     C11 : Type tache + admin 
 
Dimitri (4): 
     C3 : Creation de la branche graph_employee 
     C8 : Graphiques : projet par utilisateur 
     C9 : Merge branche graph_employee -> develop 
     Ce merge est du a un oubli de pull. C'est une erreur 
impardonnable...