text diff compare developer-tools

Vérificateur de Différences de Texte : Comparez et trouvez les différences instantanément

Comparez facilement deux textes, documents ou extraits de code avec notre vérificateur de différences. Mettez en évidence les différences, ajouts et suppressions.

Introduction

Chaque fois que vous ouvrez une pull request, examinez une révision de document ou résolvez un merge conflict, vous interagissez avec un text diff. Un diff (abréviation de difference, différence) est une représentation des modifications entre deux versions d'un texte — indiquant ce qui a été ajouté, ce qui a été supprimé et ce qui est resté identique.

Les outils de text diff sont au fondement du développement logiciel moderne. Ils propulsent les systèmes de contrôle de version, les plateformes de revue de code, les outils de collaboration et les pipelines de déploiement. Comprendre comment fonctionnent les diffs — pas seulement comment les lire, mais comment opèrent les algorithmes qui les génèrent — fait de vous un développeur plus efficace et un collaborateur plus attentif.

Cet article vous emmène des origines Unix de diff en 1974 jusqu'aux algorithmes modernes utilisés aujourd'hui par git, en expliquant les formats de diff, les merges à trois voies, les stratégies de visualisation et les bonnes pratiques.


Une Brève Histoire de diff

1974 — La Naissance de diff

Doug McIlroy a écrit l'utilitaire diff original pour Unix aux Bell Labs en 1974. Ce fut une révélation : pour la première fois, les développeurs pouvaient comparer automatiquement deux fichiers texte et produire une description structurée de leurs différences. Cela s'avéra immédiatement utile pour distribuer des patchs logiciels et suivre les modifications du code source.

1984 — GNU diff

La Free Software Foundation a publié GNU diff dans le cadre de GNU diffutils, rendant une version portable et améliorée accessible à tous. GNU diff a introduit des formats de sortie supplémentaires — context diff et unified diff — qui sont devenus des standards de l'industrie.

1986 — L'Algorithme Myers

Eugene Myers a publié son article fondateur "An O(ND) Difference Algorithm and Its Applications" en 1986. Cet algorithme — qui trouve le Shortest Edit Script (SES), le script d'édition le plus court — est devenu le fondement théorique de la plupart des implémentations modernes de diff, y compris git.

Années 1990 — diff/patch comme Format de Patch Universel

La combinaison de diff et patch est devenue le standard de facto pour la distribution de mises à jour logicielles. Les projets open source distribuaient des fichiers .patch, les contributeurs envoyaient des diffs par des listes de diffusion, et le noyau Linux a été développé et maintenu presque entièrement grâce aux workflows diff/patch par e-mail.

2005 — Git et Myers Diff

Linus Torvalds a créé git en 2005, en adoptant l'algorithme Myers comme moteur de diff par défaut. Le sous-système diff de git est devenu l'une des implémentations de diff les plus largement utilisées de l'histoire, traitant des milliards de comparaisons chaque jour sur des plateformes comme GitHub et GitLab.

Années 2010 — Histogram Diff et Visualisation Web

Git a introduit l'algorithme histogram diff comme valeur par défaut préférée pour de nombreuses opérations. Simultanément, la visualisation de diff basée sur le web a prospéré — les vues fractionnées et inline PR diffs de GitHub, les outils de revue de GitLab, et le suivi des modifications de Gerrit ont apporté les sorties de diff à une audience massive de développeurs.


Algorithmes de Diff

LCS — Plus Longue Sous-séquence Commune

L'approche classique pour calculer un diff est basée sur la Plus Longue Sous-séquence Commune (Longest Common Subsequence, LCS) de deux séquences. Le LCS est la plus longue séquence d'éléments qui apparaissent dans le même ordre relatif dans les deux entrées, mais pas nécessairement de façon contiguë.

Exemple :

  • Chaîne A = "ABCBDAB"
  • Chaîne B = "BDCAB"
  • LCS = "BCAB" (longueur 4)

Le diff est dérivé de ce qui n'est pas dans le LCS : les éléments uniquement présents dans A sont des suppressions ; ceux uniquement présents dans B sont des insertions. Le calcul du LCS requiert O(M×N) de temps et d'espace, ce qui est acceptable pour les petits fichiers mais trop lent pour les grands.

Algorithme Myers — Le Script d'Édition le Plus Court

L'algorithme de 1986 d'Eugene Myers trouve le Shortest Edit Script (SES) : le nombre minimum d'insertions et de suppressions nécessaires pour transformer la séquence A en séquence B. Ceci est équivalent à trouver le LCS, mais l'approche de Myers est bien plus efficace en pratique.

Propriétés clés :

  • Complexité temporelle : O(ND), où N = len(A) + len(B) et D = la distance d'édition
  • Complexité spatiale : O(N) avec le raffinement en espace linéaire
  • Utilise un parcours de graphe en "serpent" — un chemin diagonal à travers un graphe d'édition où chaque "serpent" représente une séquence de caractères correspondants
  • Utilisé par git, GNU diff et la plupart des outils de diff modernes

L'algorithme Myers excelle quand les modifications sont petites par rapport à la taille du fichier (D faible), ce qui est le cas courant en contrôle de version : la plupart des commits ne modifient qu'une petite fraction d'un fichier.

Patience Diff — Meilleur pour les Structures de Code

Patience diff adopte une approche différente : il commence par trouver les lignes uniques qui apparaissent exactement une fois dans les deux fichiers, les utilise comme ancres, puis compare récursivement les sections entre elles.

Cela produit des résultats bien meilleurs pour le code qui contient de nombreuses lignes structurelles identiques — pensez à }, {, return, ou les lignes vides qui apparaissent tout au long d'un fichier source. Myers pourrait correspondre à la mauvaise accolade fermante ; patience diff s'ancre sur des lignes uniques et significatives et produit des diffs beaucoup plus faciles à comprendre.

Patience diff est utilisé par Bazaar et Mercurial, et est disponible dans git via git diff --diff-algorithm=patience.

Histogram Diff — La Valeur par Défaut Moderne de Git

Histogram diff est une évolution de patience diff. Il construit un histogramme des fréquences des lignes et utilise ces informations pour prendre des décisions de correspondance plus intelligentes. Les lignes qui apparaissent souvent sont moins susceptibles d'être des ancres significatives ; les lignes rares sont de meilleures candidates.

Git a introduit histogram diff et c'est la valeur par défaut recommandée depuis environ 2012 pour de nombreux scénarios. Vous pouvez le configurer globalement avec :

git config --global diff.algorithm histogram

Formats de Sortie de Diff

Format diff Normal (Format Unix Original)

Le format de sortie original produit par diff file1.txt file2.txt :

2d1
< ligne uniquement dans file1
5,7c4,6
< ancienne ligne A
---
> nouvelle ligne A

Des commandes comme 2d1 (supprimer la ligne 2 de file1) et 5,7c4,6 (remplacer les lignes 5-7 de file1 par les lignes 4-6 de file2) rendent ce format lisible par les machines mais cryptique pour les humains.

Context Diff (flag -c)

Introduit avec GNU diff, context diff ajoute des lignes environnantes pour une meilleure lisibilité, marquant les lignes modifiées avec ! et utilisant *** / --- pour séparer les anciens et nouveaux blocs.

Format Unified Diff (flag -u) — Le Standard

Le format unified diff est le standard moderne, utilisé par git et tous les principaux workflows de patchs. Il combine l'ancien et le nouveau contenu dans un seul bloc, utilise + et - pour marquer les modifications, et inclut des en-têtes de hunk qui identifient l'emplacement de chaque modification.

Sortie git diff

La sortie de git est un unified diff avec des métadonnées supplémentaires — mode de fichier, hachages d'index, et l'en-tête diff --git qui identifie les chemins du dépôt.


Comprendre le Format Unified Diff

Décodons le format unified diff en détail :

--- a/config.py
+++ b/config.py
@@ -10,7 +10,8 @@
 DATABASE_HOST = 'localhost'
 DATABASE_PORT = 5432
-DATABASE_NAME = 'myapp_dev'
+DATABASE_NAME = 'myapp_production'
+DATABASE_SSL = True
 
 # Cache settings
 CACHE_TTL = 300

En-têtes de Fichier

--- marque le fichier original (version A) ; +++ marque le fichier nouveau (version B). Dans git, a/ et b/ sont des préfixes conventionnels.

En-têtes de Hunk

@@ -10,7 +10,8 @@

Voici l'en-tête de hunk, qui vous indique exactement où dans le fichier se trouve ce bloc de modifications :

  • -10,7 → Dans le fichier original, ce hunk commence à la ligne 10 et couvre 7 lignes
  • +10,8 → Dans le fichier nouveau, ce hunk commence à la ligne 10 et couvre 8 lignes (une ligne a été ajoutée)

Le format est toujours @@ -début,nombre +début,nombre @@.

Marqueurs de Lignes

Chaque ligne dans le corps du hunk est préfixée par l'un de ces trois caractères :

  • (espace) — ligne de contexte : inchangée, affichée pour la lisibilité
  • - (moins) — ligne supprimée : présente dans l'original, absente dans la nouvelle version
  • + (plus) — ligne ajoutée : absente dans l'original, présente dans la nouvelle version

Dans notre exemple, DATABASE_NAME = 'myapp_dev' a été supprimée et remplacée par le nom de production, et DATABASE_SSL = True est une toute nouvelle ligne. Le hunk couvre 7 lignes dans l'original (1 supprimée + 6 de contexte) et 8 lignes dans le nouveau fichier (2 ajoutées + 6 de contexte).


Diff au Niveau des Lignes, des Mots et des Caractères

Le diff standard fonctionne au niveau des lignes — chaque ligne est traitée comme une unité atomique. C'est idéal pour le code source, où les lignes sont l'unité naturelle de modification.

Diff au Niveau des Mots

Pour la prose, la documentation ou les fichiers de configuration, un diff au niveau des mots est plus informatif. Considérez cette modification :

Avant : The quick brown fox jumps over the lazy dog
Après : The quick red fox leaps over the sleeping cat

Un diff au niveau des lignes montrerait toute la ligne comme modifiée. Un diff au niveau des mots met en évidence exactement ce qui a changé :

The quick brown red fox jumps leaps over the lazy dog sleeping cat

Git prend en charge le diff au niveau des mots avec git diff --word-diff.

Diff au Niveau des Caractères

Le diff au niveau des caractères (utilisant des algorithmes comme la distance de Levenshtein) fonctionne au niveau des caractères individuels. Mieux adapté aux chaînes courtes — mots de passe, identifiants, valeurs de configuration — où même un seul caractère importe.

Tableau Comparatif

Approche Granularité Meilleur pour Exemple d'outil
Line diff Lignes Code source git diff
Word diff Mots Prose/docs git diff --word-diff
Char diff Caractères Chaînes courtes Basé sur Levenshtein
Semantic diff Nœuds AST Refactorisation difftastic

Les outils de semantic diff comme difftastic analysent le code source en un arbre syntaxique abstrait (AST) et comparent la structure de l'arbre plutôt que le texte brut, produisant des diffs qui comprennent la syntaxe du langage et ignorent les changements cosmétiques comme les espaces.


Merges à Trois Voies et Conflits de Merge

Le Modèle de Merge à Trois Voies

Quand deux personnes modifient le même fichier indépendamment, un simple diff à deux voies ne peut pas déterminer quels changements doivent prévaloir. Git utilise un merge à trois voies (three-way merge) :

  1. Base — le commit ancêtre commun
  2. Ours (le nôtre) — la version de la branche actuelle
  3. Theirs (le leur) — la version de la branche entrante

L'algorithme compare à la fois ours et theirs avec la base :

  • Si seulement ours a modifié une région → utiliser ours
  • Si seulement theirs a modifié une région → utiliser theirs
  • Si les deux ont modifié la même région différemment → conflit

Marqueurs de Conflit de Merge

Quand git ne peut pas résoudre automatiquement un conflit, il insère des marqueurs dans le fichier :

<<<<<<< HEAD
DATABASE_NAME = 'myapp_production'
=======
DATABASE_NAME = 'myapp_staging'
>>>>>>> feature/staging-config
  • Tout entre <<<<<<< et ======= est votre version (HEAD)
  • Tout entre ======= et >>>>>>> est la version entrante
  • Vous devez éditer manuellement le fichier pour résoudre le conflit, puis exécuter git add

Cas d'Usage

Revue de Code

Les diffs sont le langage de la revue de code. Les pull requests sur GitHub, GitLab et Bitbucket présentent toutes les modifications sous forme de diffs, permettant aux relecteurs de comprendre exactement ce qui a changé, ligne par ligne. Des diffs petits et ciblés améliorent considérablement la qualité et la rapidité de la revue.

Comparaison de Documents

Les équipes juridiques utilisent des outils de diff pour comparer les révisions de contrats. Les rédacteurs techniques les utilisent pour réviser les modifications de documentation. Tout workflow impliquant des documents versionnés bénéficie d'une sortie de diff structurée.

Analyse de Logs

Les administrateurs système comparent les fichiers de logs pour identifier ce qui a changé entre les exécutions — nouvelles erreurs, entrées manquantes, dérive de configuration. Des outils comme diff et colordiff font partie intégrante de la boîte à outils de l'administrateur système.

Juridique et Conformité

Les soumissions réglementaires, les pistes d'audit et les documents de conformité nécessitent souvent un enregistrement formel des modifications entre versions. Les outils de diff fournissent un enregistrement objectif et reproductible de ce qui a changé exactement, quand et comment.

Analyse de Sécurité

Les chercheurs en sécurité comparent des instantanés de configuration et des états de systèmes pour détecter des modifications non autorisées. Les systèmes de surveillance de l'intégrité des fichiers sont construits sur les principes du diff.


Approches de Visualisation

Côte à Côte (Vue Fractionnée)

Deux panneaux affichent les anciennes et nouvelles versions côte à côte, avec les modifications mises en évidence dans les lignes correspondantes. Idéal pour les grandes modifications où le contexte des deux côtés est utile.

En Ligne (Vue Unifiée)

Les suppressions et les ajouts sont affichés dans un seul flux, entremêlés avec des lignes de contexte. C'est le mode par défaut dans la plupart des outils en ligne de commande et dans la vue PR de GitHub. Idéal pour les petites modifications denses.

Vue PR de GitHub

GitHub améliore le unified diff avec la coloration syntaxique, le contexte extensible, les commentaires de revue en ligne, le basculement de vue fractionnée, et le suivi des fichiers "consultés" — rendant les grandes pull requests navigables pour les relecteurs.

Mise en Évidence des Diffs au Niveau des Mots

Des outils comme git diff --word-diff=color mettent en évidence les mots modifiés à l'intérieur des lignes, rendant visibles les modifications au niveau des caractères dans un contexte de diff au niveau des lignes. Particulièrement utile pour les fichiers de configuration et les documents en prose.


Bonnes Pratiques

  1. Gardez les commits petits et ciblés. Un diff qui change une seule chose logique est bien plus facile à réviser qu'un diff qui touche des dizaines de fichiers pour plusieurs raisons.

  2. Rédigez des messages de commit significatifs. Le diff montre ce qui a changé ; le message de commit explique pourquoi.

  3. Utilisez le bon algorithme de diff. Pour le code, histogram ou patience diff produit souvent des sorties plus lisibles que Myers. Configurez globalement : git config --global diff.algorithm histogram.

  4. Révisez les diffs avant de committer. git diff --staged montre exactement ce qui sera commité. Lisez-le toujours avant d'exécuter git commit.

  5. Utilisez word-diff pour la prose. Lors de la rédaction de documentation ou de fichiers README, git diff --word-diff est bien plus lisible que le diff au niveau des lignes.

  6. Comprenez le contexte des hunks. Les trois lignes de contexte autour de chaque hunk existent pour une raison — elles vous aident à comprendre la modification dans son contexte. Ne les ignorez pas lors de la revue.

  7. Résolvez les conflits avec soin. N'acceptez jamais un côté d'un conflit sans comprendre ce que l'autre côté a modifié. Les deux modifications peuvent être importantes.

  8. Utilisez .gitattributes pour les fichiers binaires. Indiquez à git comment gérer les fichiers binaires et spéciaux pour éviter des diffs sans signification.


Questions Fréquentes

Q : Quelle est la différence entre diff et patch ?
R : diff compare deux fichiers et produit une sortie de diff. patch prend cette sortie de diff et l'applique à un fichier pour reproduire les modifications. Ce sont des outils complémentaires conçus pour fonctionner ensemble.

Q : Quel algorithme de diff git utilise-t-il par défaut ?
R : Git utilise l'algorithme Myers par défaut, mais histogram diff est recommandé : git config --global diff.algorithm histogram.

Q : Que signifie @@ -10,7 +10,8 @@ ?
R : Le hunk commence à la ligne 10 dans les deux fichiers. Dans l'ancien fichier, il couvre 7 lignes ; dans le nouveau, 8 lignes (une ligne a été ajoutée).

Q : Puis-je comparer des fichiers binaires ?
R : Les outils de diff standard opèrent sur du texte. Pour les fichiers binaires, il existe des outils spécialisés (comme bsdiff). La plupart des outils de diff indiqueront simplement "Binary files differ".

Q : Qu'est-ce qu'un "hunk" ?
R : Un hunk est un bloc contigu de modifications dans un diff, incluant les lignes de contexte environnantes. Un seul diff peut contenir plusieurs hunks si les modifications sont réparties dans un fichier.

Q : Pourquoi git produit-il parfois des diffs déroutants pour du code déplacé ?
R : Le diff standard basé sur les lignes n'a pas de concept de "déplacement" — il ne voit que des ajouts et des suppressions. Le code déplacé apparaîtra comme supprimé à un endroit et ajouté à un autre. Des outils comme difftastic qui comprennent la structure AST peuvent détecter les déplacements.

Q : Qu'est-ce qu'un merge à trois voies ?
R : Une stratégie de merge qui utilise un ancêtre commun (base) ainsi que deux versions modifiées pour combiner intelligemment les modifications, résolvant automatiquement les éditions non conflictuelles et signalant les vrais conflits.


Comprendre le text diff n'est pas qu'une curiosité technique — c'est une compétence fondamentale pour quiconque travaille avec du texte, du code ou des documents dans le temps. De l'élégante simplicité de la commande Unix diff aux algorithmes sophistiqués qui propulsent les plateformes modernes de revue de code, le modeste diff a façonné la manière dont le logiciel est construit, révisé et maintenu pendant plus de cinq décennies.