Comparaison de changements avec git diff

Le diff prend deux ensembles de données et génère une sortie révélant les changements entre eux. git diff est une commande Git multi-usage qui exécute une fonction de différenciation sur des sources de données Git. Ces sources de données peuvent être des commits, des branches, des fichiers, etc. Ce document décrit les appels les plus courants de git diff et les modèles de workflow de différenciation. La commande git diff est souvent utilisée avec les commandes git status et git log pour analyser l'état actuel d'un dépôt Git.
 

Lecture de diffs : sorties

Format de sortie brut

Les exemples suivants sont exécutés dans un dépôt simple. Le dépôt est créé à l'aide des commandes suivantes :

$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[master (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt

Si nous exécutons git diff à ce stade, aucune sortie n'est générée. C'est un comportement attendu, car il n'y a pas de changement dans le dépôt sur lequel le diff est exécuté. Une fois que nous avons créé le dépôt et que nous avons ajouté le fichier diff_test.txt, nous pouvons modifier le fichier pour commencer à faire des essais avec la sortie de diff.

$:> echo "this is a diff example" > diff_test.txt

L'exécution de cette commande change le contenu du fichier diff_test.txt. Une fois modifié, nous voyons un diff et nous analysons la sortie. À présent, l'exécution de la commande git diff génère la sortie suivante :

diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Examinons à présent plus en détail les composants de la sortie du diff.

1. Entrée de comparaison

diff --git a/diff_test.txt b/diff_test.txt

Cette ligne affiche les sources d'entrée du diff. Nous pouvons voir que les fichiers a/diff_test.txt et b/diff_test.txt ont été transmis au diff.

2. Métadonnées

index 6b0c6cf..b37e70a 100644

Cette ligne affiche quelques métadonnées Git internes. Vous n'aurez probablement pas besoin de ces informations. Les chiffres de cette sortie correspondent aux identifiants de hachage de la version de l'objet Git.

3. Marqueurs de changements

--- a/diff_test.txt
+++ b/diff_test.txt

Ces lignes sont une légende qui assigne des symboles à chaque source d'entrée de diff. Le cas échéant, les changements apportés au fichier a/diff_test.txt sont marqués par un --- et les changements apportés au fichier b/diff_test.txt sont marqués par le symbole +++.

4. Segments de diff

La sortie de diff restante est une liste de « segments » de diff. Un diff n'affiche que les sections du fichier qui ont été modifiées. Dans notre exemple actuel, nous n'avons qu'un seul segment, car nous travaillons avec un scénario simple. Les segments ont leur propre sémantique de sortie granulaire.

@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

La première ligne est l'en-tête du segment. Chaque segment est précédé d'un en-tête inclus entre des symboles @@. Le contenu de l'en-tête est un résumé des changements apportés au fichier. Dans notre exemple simplifié, nous avons -1 +1, ce qui signifie que la première ligne a été modifiée. Dans un diff plus réaliste, vous verriez un en-tête comme :

@@ -34,6 +34,8 @@

Dans cet exemple d'en-tête, six lignes ont été extraites à partir de la ligne 34. En outre, huit lignes ont été ajoutées à partir de la ligne 34.

Le reste du contenu du segment de diff affiche les changements récents. Chaque ligne modifiée est précédée d'un symbole + ou - indiquant la version d'entrée de diff d'où viennent les changements. Comme nous l'avons vu précédemment, - indique des changements dans le fichier a/diff_test.txt et + indique des changements dans le fichier b/diff_test.txt.

Mise en évidence des changements

1. git diff --color-words

git diff dispose également d'un mode spécial pour mettre en évidence les changements avec une bien meilleure granularité : ‐‐color-words. Ce mode permet d'indexer des lignes ajoutées et supprimées avec un espace, puis de les comparer.

$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is agit difftest example

Maintenant, la sortie n'affiche que les mots qui ont changé avec un code de couleurs.

2. git diff-highlight

Si vous clonez la source Git, vous trouverez un sous-répertoire appelé contrib. Il contient une série d'outils liés à Git et d'autres éléments intéressants qui n'ont pas encore été intégrés aux commandes de base de Git. L'un d'entre eux est un script Perl appelé diff-highlight. diff-highlight apparie les lignes correspondantes de la sortie de diff et met en évidence les fragments de sous-mots qui ont changé.

$:> git diff | /votre/chemin/local/vers/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Nous avons maintenant réduit notre diff au plus petit changement possible.

Comparaison de fichiers binaires

En plus des utilitaires de fichiers texte que nous avons présentés jusqu'ici, git diff peut être exécutée sur des fichiers binaires. Malheureusement, la sortie par défaut n'est pas très utile.

$:> git diff
Binary files a/script.pdf and b/script.pdf differ

Git dispose d'une fonction qui vous permet de spécifier une commande shell pour transformer le contenu de vos fichiers binaires en texte avant d'effectuer le diff. Cela nécessite cependant un peu de configuration. Tout d'abord, vous devez spécifier un filtre textconv décrivant comment convertir un certain type de fichier binaire en fichier texte. Nous utilisons un simple utilitaire appelé pdftohtml (disponible via homebrew) pour convertir les fichiers PDF en fichiers HTML lisibles par l'homme. Vous pouvez le configurer pour un seul dépôt en modifiant votre fichier .git/config ou globalement en modifiant ~ /.gitconfig.

[diff "pdfconv"]
textconv=pdftohtml -stdout

Il vous suffit alors d'associer un ou plusieurs modèles de fichiers à notre filtre pdfconv. Pour cela, créez un fichier .gitattributes à la racine de votre dépôt.

*.pdf diff=pdfconv

Une fois configuré, git diff exécutera d'abord le fichier binaire via le script de conversion configuré et effectue un diff sur la sortie du convertisseur. La même technique peut être appliquée pour obtenir des diffs exploitables à partir de toutes sortes de fichiers binaires, par exemple : pour les fichiers ZIP, JAR et autres archives, utiliser unzip -l (ou une commande similaire) au lieu de pdf2html vous montrera les chemins qui ont été ajoutés ou supprimés entre les images de commit. La commande exiv2 peut être utilisée pour afficher les changements apportés aux métadonnées comme les documents de dimensions d'image : des outils de conversion existent pour transformer les formats de fichiers .odf, .doc et autres en texte brut. En cas de problème, les chaînes de caractères fonctionnent souvent pour les fichiers binaires pour lesquels il n'existe pas de convertisseur formel.

Comparaison de fichiers : git diff file

La commande git diff peut recevoir une option explicite de chemin d'accès au fichier. Lorsqu'un chemin de fichier est transmis à git diff, l'opération de diff sera étendue au fichier spécifié. Les exemples ci-dessous illustre cette utilisation.

git diff HEAD ./chemin/vers/fichier

Cet exemple est limité à ./path/to/file. Lorsqu'il est appelé, il comparera les changements spécifiques dans le répertoire de travail, par rapport à l'index, en indiquant les changements qui ne sont pas encore stagés. Par défaut, git diff effectue la comparaison par rapport à HEAD. Oublier HEAD dans l'exemple ci-dessus, git diff ./path/to/file, a le même résultat.

git diff --cached ./path/to/file

Lorsque la commande git diff est appelée avec l'option --cached, le diff compare les changements stagés avec le dépôt local. L'option --cached est synonyme de --staged.

Comparaison de tous les changements

Appeler git diff sans chemin d'accès au fichier comparera les changements dans l'ensemble du dépôt. Les exemples ci-dessus, propres à des fichiers, peuvent être appelés sans l'argument ./path/to/file et génèrent la même sortie pour tous les fichiers du dépôt local.

Changements depuis le dernier commit

Par défaut, git diff vous montre tous les changements non commités depuis le dernier commit.

git diff

Comparaison de fichiers entre deux commits différents

Des réfs Git à des commits sur lesquels effectuer un diff peuvent être transmises à git diff. Exemples de réfs : HEAD, tags et noms de branche. Chaque commit dans Git possède un ID de commit que vous pouvez obtenir en exécutant GIT LOG. Vous pouvez également transmettre cet ID de commit à git diff.

git log --prety=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body
$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a

Comparaison de branches

Comparaison de deux branches

Les branches sont comparées, comme toutes les autres entrées de réf, à git diff.

git diff branch1..other-feature-branch

Cet exemple présente l'opérateur de point. Les deux points de cet exemple indiquent que la différence entre les deux entrées est l'extrémité des deux branches. Le même effet se produit si les points sont omis et qu'un espace est utilisé entre les branches. En outre, il existe un opérateur à trois points :

git diff branch1...other-feature-branch

L'opérateur à trois points initie le diff en modifiant le premier paramètre d'entrée, branch1. Il change branch1 en une réf de commit d'ancêtre commun entre les deux entrées du diff, l'ancêtre commun de branch1 et other-feature-branch. Le dernier paramètre d'entrée reste inchangé en tant qu'extrémité de other-feature-branch.

Comparaison de fichiers de deux branches

Pour comparer un dossier spécifique entre plusieurs branches, transmettez le chemin d'accès au dossier comme troisième argument à git diff.

git diff master new_branch ./diff_test.txt

Résumé

Cette page présentait le processus de différenciation Git et la commande git diff. Nous y avons appris à lire une sortie git diff et les diverses données qu'elle comprend. Nous vous avons montré comment modifier la sortie git diff avec mise en évidence et couleurs. Nous avons discuté de différentes stratégies de différenciation, comme la comparaison de fichiers dans des branches et des commits spécifiques. Outre la commande git diff, nous avons également utilisé git log et git checkout.

Prêt à découvrir Git ?

Essayez ce tutoriel interactif.

Démarrez maintenant