Revisões de código, relatos de bugs e patches trocados por e-mail usam quase sempre o formato unified diff. git diff, diff -u e o "raw diff" do GitHub usam todos esse formato. À primeira vista parece cheio de símbolos, mas as regras são simples.
A forma geral
@@ -1,5 +1,6 @@ def greet(name):- print("Hello " + name)+ message = f"Hello, {name}!"+ print(message) def main(): greet("world")
De cima para baixo vêm os cabeçalhos estendidos do git, os cabeçalhos de arquivo (---, +++) e os hunks (blocos que começam com @@). Um arquivo pode ter vários hunks, e um patch pode ter vários arquivos.
Cabeçalhos de arquivo: --- e +++
--- a/greet.pyé o arquivo antes da mudança;+++ b/greet.pyé o arquivo depois.- O git acrescenta
a/eb/antes do caminho. Por isso, ao aplicar com o comandopatch, usa-se-p1para descartar o primeiro componente do caminho. - Um arquivo novo aparece como
--- /dev/null, e um arquivo apagado como+++ /dev/null. - O GNU diff às vezes acrescenta a data de modificação depois do nome do arquivo.
Cabeçalho de hunk @@ -a,b +c,d @@
@@ -1,5 +1,6 @@ significa "mostra 5 linhas a partir da linha 1 do arquivo antes da mudança e 6 linhas a partir da linha 1 do arquivo depois".
- O primeiro número é o número da linha inicial; o que vem depois da vírgula é quantas linhas o hunk ocupa (incluindo as de contexto).
- Se a contagem é 1, ela é omitida junto com a vírgula.
@@ -7 +7 @@é um hunk de uma linha só, a linha 7. - Se a contagem é 0, não há linhas daquele lado.
@@ -3,0 +4,2 @@significa que duas linhas novas entraram depois da linha 3 do original. Comparando com um arquivo vazio, aparece-0,0. - Depois do segundo
@@pode vir um texto, como o nome de uma função (@@ -40,7 +40,8 @@ def main():). É uma informação de referência que indica em qual função o hunk está, e é ignorada na aplicação.
Contando no exemplo acima, as linhas de contexto (as que começam com espaço) são 4: def greet(name):, a linha em branco, def main(): e greet("world"). Antes da mudança são 4 de contexto mais 1 linha - = 5; depois, 4 de contexto mais 2 linhas + = 6. Por isso o cabeçalho é -1,5 +1,6.
Os três tipos de linha no corpo
| Primeiro caractere | Significado |
|---|---|
| Espaço | Linha de contexto, igual nos dois lados |
- | Linha que só existe antes (removida) |
+ | Linha que só existe depois (adicionada) |
O contexto padrão é de 3 linhas antes e depois da mudança (pode ser alterado, como em git diff -U5). As linhas de contexto servem para encontrar a posição certa ao aplicar o patch. Mesmo que os números de linha estejam um pouco deslocados, se o contexto bater o patch aplica a mudança em outra posição (offset).
Uma linha corrigida aparece como um par: uma linha - seguida de uma linha +. O formato unified não tem um símbolo próprio para "modificado", então o truque é ler alinhando o grupo de linhas - consecutivas com o grupo de linhas + logo abaixo.
\ No newline at end of file
@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080
Indica que a linha logo acima é a última do arquivo e não termina com um caractere de quebra de linha. No exemplo, o conteúdo é o mesmo, e só o arquivo depois da mudança ganhou a quebra de linha final. Veja mais em Caracteres de fim de linha e diferenças invisíveis.
Cabeçalhos estendidos do git
As linhas que vêm depois de diff --git a/caminho b/caminho são informações adicionais exclusivas do git.
index 3b18e51..a6f4c2d 100644— o início dos hashes do conteúdo do arquivo antes e depois, e o modo do arquivo (100644 é um arquivo comum; 100755, um executável)new file mode 100644/deleted file mode 100644— criação ou exclusão do arquivoold mode 100644/new mode 100755— só a permissão de execução mudou (pode aparecer sem nenhum hunk de conteúdo)similarity index 90%,rename from caminho-antigo,rename to caminho-novo— renomeação (o conteúdo é 90% igual)Binary files a/logo.png and b/logo.png differ— para arquivos binários, só esta linha em vez do conteúdo
Dicas úteis na revisão
- Olhar primeiro a diferença nas contagens de linha do cabeçalho do hunk dá uma ideia do tamanho da mudança.
-10,7 +10,30significa 23 linhas a mais. - Para filtrar hunks em que só mudaram espaços, use
git diff -w. É especialmente útil em commits que misturam ajuste de indentação com mudanças reais (Opções de ignorar espaços). - Para ver o que mudou dentro de uma linha, use
git diff --word-diffou cole o diff em uma ferramenta com destaque dentro da linha, como este site. - Antes de aplicar um patch, confirme que ele se aplica sem problemas com
git apply --check arquivo.patch. Fora de um repositório git, usepatch -p1 --dry-run < arquivo.patch.
Experimente nesta ferramenta
A visualização unificada do comparador de textos mostra o grupo - e depois o grupo +, na mesma ordem deste formato, e destaca mais uma vez as palavras alteradas dentro da linha. O botão patch da barra de resultados copia o texto unified diff padrão, e o botão de salvar ao lado baixa um arquivo diff.patch. Um patch gerado com todas as opções de ignorar desativadas pode ser aplicado ao original com patch -p1 ou git apply.