Básico de diff e patch - Gerando e Aplicando Diferenças
O Que Você Vai Aprender
- Como comparar dois arquivos com
diffe interpretar a saída - Como interpretar o formato unified diff (
diff -u) - Como aplicar um arquivo de patch com
patch - Como reverter um patch com
patch -R
Resumo Rápido
- 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
Pré-requisitos
- SO: Ubuntu ou qualquer distribuição Linux
diffepatchjá vêm instalados por padrão na maioria dos sistemas Linux
O Que é o diff?
diff compara dois arquivos linha por linha e mostra o que mudou entre eles. É usado diariamente para revisar alterações em código-fonte, comparar arquivos de configuração com backups e gerar arquivos de patch para distribuição.
Como Usar o diff
Comparação Básica
$ diff old.txt new.txt
Se não houver diferenças, nada é impresso. Quando há diferenças, a saída no formato "normal" padrão se parece com isto:
2c2 < conteudo antigo --- > conteudo novo
O formato normal é difícil de ler e não é adequado para o patch. Use o formato unificado em vez disso.
Formato Unificado (-u)
A opção -u produz saída em formato unificado, o formato padrão para arquivos de patch.
$ diff -u old.txt new.txt
Exemplo de saída:
--- 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:
| Símbolo | Significado |
|---|---|
--- |
Arquivo original (antes) |
+++ |
Arquivo modificado (depois) |
@@ |
Cabeçalho do hunk com números de linha |
- |
Linha removida |
+ |
Linha adicionada |
(espaço) |
Linha de contexto (sem alteração) |
O cabeçalho do hunk @@ -1,5 +1,5 @@ significa: começando na linha 1, mostrando 5 linhas do arquivo antigo / 5 linhas do arquivo novo. Três linhas de contexto antes e depois de cada alteração são incluídas por padrão.
Comparação Recursiva de Diretórios (-r)
Use -r com -u para comparar árvores de diretórios inteiras:
$ diff -ur dir_old/ dir_new/
Cada arquivo alterado aparece como um bloco unified diff separado na saída.
Opções Úteis do diff
| Opção | Descrição |
|---|---|
-u |
Formato unificado (necessário para patch) |
-r |
Recursivo (comparar diretórios) |
-i |
Ignorar diferenças de maiúsculas/minúsculas |
-w |
Ignorar todos os espaços em branco |
-b |
Ignorar alterações na quantidade de espaços |
--color |
Colorir a saída (GNU diff) |
Salvando o Diff em um Arquivo de Patch
Redirecione a saída 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 é o que você passa para o patch ao aplicar as alterações.
O Que é o patch?
patch recebe um arquivo diff produzido pelo diff e aplica essas alterações a um arquivo ou diretório alvo. É assim que correções de bugs e patches de segurança são distribuídos em software de código aberto: o mantenedor executa diff, envia o arquivo .patch, e os usuários executam patch para aplicá-lo.
Como Usar o patch
Entendendo o Nível de Remoção -p
A opção -p controla quantos componentes iniciais do caminho devem ser removidos dos nomes de arquivos dentro do cabeçalho do patch.
--- a/src/config.txt ← com -p1, interpretado como "src/config.txt"
+++ b/src/config.txt
| Opção | Comportamento |
|---|---|
-p0 |
Usar o caminho completo como está |
-p1 |
Remover um componente inicial (remove a/ ou b/) |
Patches gerados pelo Git sempre incluem os prefixos a/ e b/, então -p1 é a escolha mais comum para patches do Git. Para patches criados com diff -u simples (sem prefixo), use -p0.
Dry Run Primeiro
Sempre faça uma prévia 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 não reportar erros, prossiga com a aplicação 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 não corresponde ao estado atual do arquivo alvo. O arquivo pode já ter sido patcheado ou foi modificado independentemente. Use --dry-run para diagnosticar antes de tentar.
Rejeição 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 alterações manualmente.
Revertendo um Patch
A flag -R reverte um patch, aplicando-o desfaz a alteração 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 após o patch ter sido aplicado, a reversão pode falhar ou produzir resultados incorretos.
Fluxos de Trabalho Práticos
Compartilhando uma Alteração em Arquivo de Configuração
# 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 Código 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 Compatível com Git
Ao trabalhar em um repositório Git, git diff produz uma saída que o patch -p1 pode consumir diretamente:
$ git diff > my-changes.patch $ patch -p1 < my-changes.patch
Para alterações já commitadas, git format-patch é mais apropriado pois preserva os metadados do commit.
Resumo
| Comando | Propósito |
|---|---|
diff -u old new |
Mostrar diff unificado |
diff -ur dir1/ dir2/ |
Comparar diretórios recursivamente |
diff -u old new > fix.patch |
Gerar um arquivo de patch |
patch --dry-run -p0 < fix.patch |
Prévia da aplicação 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