diff & patch

Posté le dim 25 septembre 2016 dans devtools

diff et patch sont deux outils en ligne de commande.

diff, va vous permettre de comparer le contenu de deux fichiers ou dossiers et de voir les ajouts et/ou suppressions qu'il y a eu entre chaque fichier. Ce résultat peut être stocké dans un fichier, que l'on nomme patch.

La commande patch permet d'appliquer un patch. Le but est donc de pouvoir réappliquer une modification sur un fichier ou dossier en version originale.

diff

  • diff -q fichier1 fichier2 permet de savoir si les fichiers sont différents.
  • diff -s fichier1 fichier2 permet de savoir si les fichiers sont identiques.
  • diff -y fichier1 fichier2 affiche les deux fichiers côte à côte.
  • diff -u fichier1 fichier2 imprime (par défaut) 3 lignes qui entourent la différence.
  • diff -a fichier1 fichier2 traite les fichiers comme des fichiers textes.
  • diff --color=auto fichier1 fichier2 ajoute de la couleur au résultat.
  • diff -r dossier1 dossier2 permet de comparer deux dossiers récursivement.
  • diff -N dossier1 dossier2 traite les fichiers absents comme étant vides.

Il y a évidemment une multitude d'autres options que vous découvrirez dans man diff.

Meld, Kdiff3 et Kompare sont des versions graphiques de diff. Le premier est basé sur GTK, les deux autres sur Qt.

Créer un patch

Admettons que votre répertoire de travail est $HOME/projetX. Avant de le modifier, faite en une copie cp -r $HOME/projetX $HOME/projetX.orig. Voici le fichier hello.c original :

#include <stdio.h>
int main()
{
    printf("Hello\n");
    return 0;
}

Que vous modifiez en :

#include <stdio.h>
int main()
{
    printf("Hello World !!!\n");
    return 0;
}

La commande diff -Naur projetX.orig projetX donne comme résultat :

diff -Naur projetX.orig/hello.c projetX/hello.c
--- projetX.orig/hello.c  2016-09-25 03:48:01.216191638 +0000
+++ projetX/hello.c 2016-09-25 03:48:12.059524697 +0000
@@ -1,6 +1,6 @@
 #include <stdio.h>
 int main()
 {
-    printf("Hello\n");
+    printf("Hello world !!!\n");
     return 0;
 }

Pour créer le patch, il suffit de rediriger la commande diff dans un fichier : diff -Naur projetX.orig projetX > $HOME/bug1.patch

Pour la suite supprimer le dossier projectX rm -r $HOME/projetX et renommer projetX.orig mv projetX.orig projetX (on applique le patch sur la version d'origine).

Appliquer un patch

Placez-vous dans le dossier parent de votre projet. La commande patch -p0 < $hOME/bug1.patch appliquera votre patch sur le dossier projetX.

Si vous avez renommé, ou souhaitez appliquer le patch sur une copie du projet, appliquez la commande depuis le dossier du projet avec l'option -p1: patch -p1 < $HOME/bug1.patch.

Cette option -p1 permet à la commande patch d'enlever un niveau de dossier au chemin indiqué dans le fichier .patch.

Il ne faut pas oublier que pour créer un patch, il faut conserver une copie non modifiée du projet. Ceci est grandement facilité en utilisant des outils de gestion de version comme git ou svn.

Est-ce vraiment utile tout cela ?

Voici quelques exemples d'utilisation.

Exemple 1

Vous venez de modifier votre site web, votre modification porte sur plusieurs fichiers php, js, html et css. Soit vous transférez complètement la dernière version de votre site, soit uniquement les fichiers impactés.

Dans le premier cas, cela peut prendre un petit peu de temps. Dans le second cas, il faut veiller à ne pas oublier de fichiers.

Une autre solution est possible, créer un patch et appliquer ce patch sur le serveur. Le patch est de petite taille comparée à la totalité du site (transfert instantané), aucune modification n'est oubliée.

Ici, il faut soit un accès en ssh à votre serveur, soit une interface web qui permet d'appliquer un patch.

Exemple 2

Admettons que vous modifiez un fichier .c du kernel, le meilleur moyen pour diffuser ou conserver cette modification est un fichier patch.

Lorsque vous recevez un patch, vous pouvez l'éditer et voir les modifications qui seront apportées à l'arborescence.

Votre patch sera même peut-être applicable sur les versions successives du kernel. En une commande vous pouvez réappliquer vos modifications.

Par contre si vous diffusez une archive complète du kernel contenant votre modification, comment faire pour intégrer votre modification au kernel suivant ou à une version sur laquelle d'autres patchs ont déjà été appliqués ?