Basico de diff e patch - Gerando e Aplicando Diferencas

Basico de diff e patch - Gerando e Aplicando Diferencas

O Que Voce Vai Aprender

  • Como comparar dois arquivos com diff e interpretar a saida
  • Como interpretar o formato unified diff (diff -u)
  • Como aplicar um arquivo de patch com patch
  • Como reverter um patch com patch -R

Resumo Rapido

  • Ver diff: diff -u arquivo_antigo arquivo_novo
  • Salvar patch: diff -u arquivo_antigo arquivo_novo > changes.patch
  • Aplicar patch: patch -p0 < changes.patch
  • Reverter patch: patch -R -p0 < changes.patch

Pre-requisitos

  • SO: Ubuntu ou qualquer distribuicao Linux
  • diff e patch ja vem instalados por padrao na maioria dos sistemas Linux

O Que e o diff?

diff compara dois arquivos linha por linha e mostra o que mudou entre eles. E usado diariamente para revisar alteracoes em codigo-fonte, comparar arquivos de configuracao com backups e gerar arquivos de patch para distribuicao.

Como Usar o diff

Comparacao Basica

$ diff old.txt new.txt

Se nao houver diferencas, nada e impresso. Quando ha diferencas, a saida no formato "normal" padrao se parece com isto:

2c2
< conteudo antigo
---
> conteudo novo

O formato normal e dificil de ler e nao e adequado para o patch. Use o formato unificado em vez disso.

Formato Unificado (-u)

A opcao -u produz saida em formato unificado, o formato padrao para arquivos de patch.

$ diff -u old.txt new.txt

Exemplo de saida:

--- old.txt	2026-06-01 10:00:00.000000000 +0000
+++ new.txt	2026-06-01 10:05:00.000000000 +0000
@@ -1,5 +1,5 @@
 line1 (unchanged)
-old line2
+new line2
 line3 (unchanged)

Como interpretar:

Simbolo Significado
--- Arquivo original (antes)
+++ Arquivo modificado (depois)
@@ Cabecalho do hunk com numeros de linha
- Linha removida
+ Linha adicionada
(espaco) Linha de contexto (sem alteracao)

O cabecalho do hunk @@ -1,5 +1,5 @@ significa: comecando na linha 1, mostrando 5 linhas do arquivo antigo / 5 linhas do arquivo novo. Tres linhas de contexto antes e depois de cada alteracao sao incluidas por padrao.

Comparacao Recursiva de Diretorios (-r)

Use -r com -u para comparar arvores de diretorios inteiras:

$ diff -ur dir_old/ dir_new/

Cada arquivo alterado aparece como um bloco unified diff separado na saida.

Opcoes Uteis do diff

Opcao Descricao
-u Formato unificado (necessario para patch)
-r Recursivo (comparar diretorios)
-i Ignorar diferencas de maiusculas/minusculas
-w Ignorar todos os espacos em branco
-b Ignorar alteracoes na quantidade de espacos
--color Colorir a saida (GNU diff)

Salvando o Diff em um Arquivo de Patch

Redirecione a saida do diff para um arquivo:

# Arquivo unico
$ diff -u original.txt modified.txt > changes.patch

# Diretorio inteiro
$ diff -ur dir_old/ dir_new/ > project.patch

Este arquivo e o que voce passa para o patch ao aplicar as alteracoes.

O Que e o patch?

patch recebe um arquivo diff produzido pelo diff e aplica essas alteracoes a um arquivo ou diretorio alvo. E assim que correcoes de bugs e patches de seguranca sao distribuidos em software de codigo aberto: o mantenedor executa diff, envia o arquivo .patch, e os usuarios executam patch para aplica-lo.

Como Usar o patch

Entendendo o Nivel de Remocao -p

A opcao -p controla quantos componentes iniciais do caminho devem ser removidos dos nomes de arquivos dentro do cabecalho do patch.

--- a/src/config.txt    ← com -p1, interpretado como "src/config.txt"
+++ b/src/config.txt
Opcao Comportamento
-p0 Usar o caminho completo como esta
-p1 Remover um componente inicial (remove a/ ou b/)

Patches gerados pelo Git sempre incluem os prefixos a/ e b/, entao -p1 e a escolha mais comum para patches do Git. Para patches criados com diff -u simples (sem prefixo), use -p0.

Dry Run Primeiro

Sempre faca uma previa antes de aplicar:

$ patch --dry-run -p0 < changes.patch

--dry-run verifica se o patch pode ser aplicado sem problemas sem modificar nenhum arquivo. Se nao reportar erros, prossiga com a aplicacao real.

Aplicando um Patch

Para patches criados com diff -u (simples, sem prefixo a//b/):

$ patch -p0 < changes.patch

Para patches gerados pelo Git ou patches com prefixos a//b/:

$ patch -p1 < project.patch

Se o patch reportar "Hunk FAILED", o patch nao corresponde ao estado atual do arquivo alvo. O arquivo pode ja ter sido patcheado ou foi modificado independentemente. Use --dry-run para diagnosticar antes de tentar.

Rejeicao de Hunks

Quando um hunk falha, o patch grava as partes rejeitadas em um arquivo .rej (ex.: config.txt.rej). Inspecione-o para aplicar as alteracoes manualmente.

Revertendo um Patch

A flag -R reverte um patch, aplicando-o desfaz a alteracao original:

$ patch -R -p0 < changes.patch

# Patch em formato Git
$ patch -R -p1 < project.patch

Reverter requer que as linhas de contexto no patch ainda correspondam ao arquivo alvo. Se o arquivo foi alterado apos o patch ter sido aplicado, a reversao pode falhar ou produzir resultados incorretos.

Fluxos de Trabalho Praticos

Compartilhando uma Alteracao em Arquivo de Configuracao

# 1. Salvar o original
$ cp nginx.conf nginx.conf.orig

# 2. Editar o arquivo
$ vim nginx.conf

# 3. Gerar o patch
$ diff -u nginx.conf.orig nginx.conf > nginx-fix.patch

# 4. Destinatario aplica o patch
$ patch --dry-run -p0 < nginx-fix.patch
$ patch -p0 < nginx-fix.patch

Aplicando um Patch de Codigo Aberto

# Executar a partir do diretorio raiz do projeto
$ patch --dry-run -p1 < bugfix.patch
$ patch -p1 < bugfix.patch

# Desfazer se algo der errado
$ patch -R -p1 < bugfix.patch

Gerando um Patch Compativel com Git

Ao trabalhar em um repositorio Git, git diff produz uma saida que o patch -p1 pode consumir diretamente:

$ git diff > my-changes.patch
$ patch -p1 < my-changes.patch

Para alteracoes ja commitadas, git format-patch e mais apropriado pois preserva os metadados do commit.

Resumo

Comando Proposito
diff -u old new Mostrar diff unificado
diff -ur dir1/ dir2/ Comparar diretorios recursivamente
diff -u old new > fix.patch Gerar um arquivo de patch
patch --dry-run -p0 < fix.patch Previa da aplicacao do patch
patch -p0 < fix.patch Aplicar patch (formato simples)
patch -p1 < fix.patch Aplicar patch (formato Git)
patch -R -p0 < fix.patch Reverter um patch

Modelos para Copiar e Colar

# Gerar patch
diff -u original.txt modified.txt > changes.patch

# Previa
patch --dry-run -p0 < changes.patch

# Aplicar
patch -p0 < changes.patch

# Reverter
patch -R -p0 < changes.patch

Proximas Leituras