Applicare una patch

Tux patch
Tux patch

Dimentichiamoci per un attimo che esista Git e, più in generale, i software di gestione del versionamento. All’origine dei tempi, come si applicavano le modifiche ai file quando si faceva sviluppo in team? Ovviamente quanto segue è comunque utile e può essere utilizzato in sistuazioni in cui dobbiamo emendare singoli file.

Unix ha tuttora, compreso Linux, un comando di utilità molto potente: il comando diff, che è un utilissimo strumento per confrontare file di testo. È utile per esempio per individuare i punti in cui un programma è stato modificato rispetto ad una versione iniziale, magari introducendo dei bug non intenzionali, come capita spesso.

Meno comune è il suo uso per applicare velocemente le modifiche di una nuova versione ad uno stesso file di una versione diversa.

Potremmo semplicemente guardarci il file vecchio con un occhio, il file nuovo con un altro e applicare a mano le novità presenti nel nuovo dentro al file vecchio.

Ma l’essere umano è naturalmente fallibile ed è consigliabile operare in altro modo.

In Linux/Unix esiste un comando gemello di diff che è patch. Patch prende un file di differenze e modifica il file argomento applicando le modifiche contenute nel file di differenze.

Il file di differenze è l’output del comando diff. Vediamo un esempio.

Scrivo un bellissimo programma

Il bellissimo programma è questo, si chiama, tanto per non discostarci troppo dalla tradizione, hello.c:

#include <stdio.h> 

int main() {
	printf("Hello World\n");
}

Un collega scrive una versione più completa

Un collega che sta lavorando sul mio stesso progetto, fa una modifica al file e produce il nuovo file hello_new.c: (ovviamente al giorno d’oggi nessuno più si sogna di lavorare così, ma riportiamoci per un attimo nel passato, come abbiamo detto ll’inizio):

#include <stdio.h>

int main(int argc, char *argv[]) {
	printf("Hello World\n");
	return 0;
}

Il suo programma è più figo perché prevede che gli si possano passare dei parametri in ingresso.

Ora devo aggiornare la mia copia

Come faccio da aggiornare la mia copia senza fare errori? Ovviamente, non riportando a mano (e a occhio) le modifiche.

Uso invece il file differenza, un cerotto, detto patch: non è altro che l’output del comando diff:

$ diff hello.c hello_new.c 
1c1
< #include <stdio.h> 
---
> #include <stdio.h>
3c3
< int main() {
---
> int main(int argc, char *argv[]) {
4a5
> 	return 0;

Ora questo ouput lo mettiamo su un file che chiamiamo hello.patch

$ diff hello.c hello_new.c > hello.patch

L’applicazione del cerotto si fa con il comando:

$ patch [file da sanare] [cerotto]

Nel nostro caso, prima mi faccio un backup del file da sanare:

$ cp hello.c hello.orig.c

e poi applico la patch

$ patch hello.c hello.patch

A questo punto il file hello.c è cambiato, recependo gli aggiornamenti:

$ cat hello.c
#include <stdio.h>

int main(int argc, char *argv[]) {
	printf("Hello World\n");
	return 0;
}

È possibile creare la copia di backup contestualmente con l’applicazione della patch, senza cioè farlo a mano con un secondo comando come abbiamo fatto noi: specificando l’opzione -b, patch prima crea la copia di backup e poi applica le modifiche:

$ patch -b hello.c hello.patch 
patching file hello.c
$ ll
totale 28
drwxrwxr-x 2 marcob marcob 4096 ott 25 11:58 ./
drwxrwxr-x 3 marcob marcob 4096 ott 25 10:52 ../
-rw-rw-r-- 1 marcob marcob  173 ott 25 10:54 diagram.txt
-rw-rw-r-- 1 marcob marcob   94 ott 25 11:58 hello.c
-rw-rw-r-- 1 marcob marcob   62 ott 25 11:56 hello.c.orig <---- creato grazie all'opzione -b
-rw-rw-r-- 1 marcob marcob   94 ott 25 10:54 hello_new.c
-rw-rw-r-- 1 marcob marcob  128 ott 25 11:57 hello.patch

È bello Nautilus (il file manager di GNOME Linux) che mostra delle icone azzeccate:

patch
patch: Nautilus mostra icone constestuali 🙂

… e Git?

Questo comando è integrato in Git, ad esempio quando eseguiamo il comando di merge di due linee di sviluppo (branch). Diciamo che il bello di questo comando è il principio ma oggigiorno è annegato in strumenti ben più complessi per la gestione delle versioni dei file.

Riferimenti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.