Tutorial

git log, diff, show e blame: como ler o histórico do projeto no Git

Atualizado: · Skillaria.Top

O git log mostra a lista de commits e filtra por autor, data, arquivo e texto; o git diff compara a pasta de trabalho, o índice e quaisquer commits; o git show exibe um commit inteiro; o git blame mostra qual commit alterou por último cada linha de um arquivo.

Quatro comandos resolvem quase todas as perguntas sobre o histórico de um projeto. O git log responde "o que aconteceu", o git diff "o que exatamente mudou", o git show "o que há dentro de um commit específico" e o git blame "quem escreveu esta linha e quando". A seguir, técnicas práticas para cada um, com as flags que realmente se usam no desenvolvimento do dia a dia.

git log: a lista de commits

Sem argumentos, o git log exibe os commits da branch atual do mais novo para o mais antigo: hash SHA-1 completo, autor, data e mensagem. A saída abre num paginador (normalmente o less): espaço — próxima página, /texto — busca, q — sair.

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: cache das respostas da API

Não é preciso copiar o hash inteiro: o Git entende qualquer prefixo único a partir de 4 caracteres; na prática, 7 bastam.

Saída compacta: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: cache das respostas da API
# 1c02e8f fix: timeout das requisições
# 9a4b3c2 refactor: cliente movido para um módulo

A flag -10 (ou -n 10) limita o número de commits. Entre parênteses ficam os ponteiros: onde estão o HEAD, as branches locais e remotas e as tags.

Grafo de branches: git log --graph

Quem procura "git graph" normalmente quer exatamente isto: visualizar ramificações e merges direto no terminal.

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: login por token
# | * 7be41d0 (HEAD -> main) feat: cache das respostas da API
# |/
# * 1c02e8f fix: timeout das requisições
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: busca
# |/
# * 9a4b3c2 refactor: cliente movido para um módulo

--all mostra todas as branches, e não só a atual. Vale criar um alias: git config --global alias.lg "log --oneline --graph --all --decorate", e depois basta git lg.

Formato próprio: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: cache das respostas da API

Principais placeholders: %h — hash curto, %H — completo, %an — autor, %ae — e-mail dele, %ad — data do autor, %ar — data relativa ("2 days ago"), %s — título da mensagem.

Como filtrar o histórico no git log

Por autor e data

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author aceita expressão regular e busca no nome e no e-mail. O Git entende datas tanto em formato livre quanto em ISO.

Pelo texto da mensagem

git log --grep="fix" -i --oneline

-i torna a busca insensível a maiúsculas e minúsculas. Se o seu time coloca o número da tarefa nas mensagens, assim você encontra rápido todos os commits de uma tarefa.

Por arquivo ou pasta

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

O traço duplo separa os caminhos das branches. --follow continua o histórico do arquivo através de renomeações (funciona para um arquivo só), -p mostra o patch de cada commit.

Pelo código alterado: a busca "picareta"

git log -S "retry_count" --oneline     # commits em que mudou o número de ocorrências da string
git log -G "timeout\s*=" --oneline    # commits cujo diff tem linhas que casam com a regex

-S encontra o commit em que uma função ou variável foi adicionada ou removida — indispensável quando você precisa descobrir para onde foi um trecho de código.

Intervalos de commits

git log main..feature      # o que está em feature, mas não em main
git log origin/main..HEAD  # meus commits locais ainda não enviados
git log --no-merges        # sem commits de merge
git log --stat             # quais arquivos e quantas linhas mudaram

git diff: o que exatamente mudou

O principal a entender sobre o git diff é quais dois estados ele compara. A confusão aqui é a origem da pergunta "por que o diff está vazio, se eu mudei tudo?".

ComandoO que compara
git diffpasta de trabalho vs. índice (alterações não preparadas)
git diff --staged (--cached)índice vs. último commit (o que vai entrar no commit)
git diff HEADpasta de trabalho vs. último commit (tudo junto)
git diff A Bdois commits, branches ou tags
git diff A...Balterações em B desde que ele se separou de A

Se você fez git add, o git diff comum fica vazio — as alterações já estão no índice; use --staged. Arquivos novos, nunca adicionados, o diff simplesmente não mostra.

Como ler a saída do diff

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

Linhas com - foram removidas, com + adicionadas, as demais são contexto. O cabeçalho @@ -10,7 +10,7 @@ significa: o trecho começa na linha 10 e ocupa 7 linhas nas versões antiga e nova.

Flags úteis do git diff

git diff --stat main feature      # resumo por arquivo
git diff --name-only HEAD~3       # só os nomes dos arquivos alterados
git diff --word-diff               # alterações por palavra, prático para textos
git diff -w                        # ignorar alterações de espaços
git diff main feature -- src/      # limitar a uma pasta

Antes de cada commit, vale olhar o git diff --staged: é a última chance de notar um print de depuração ou um arquivo adicionado sem querer.

git show: um commit inteiro

O git show exibe os metadados do commit e o diff dele em relação ao pai. Sem argumentos, mostra o último commit.

git show 7be41d0
git show HEAD~2 --stat           # sem patch, só o resumo
git show v1.2.0                  # tag: anotação e commit
git show main:src/config.py      # o arquivo como estava no commit

A última forma, <revisão>:<caminho>, é especialmente útil: dá para ver a versão antiga de um arquivo sem mudar para ela. Redirecione a saída para um arquivo e você recupera conteúdo apagado sem checkout.

git blame: quem alterou esta linha

git blame arquivo mostra, para cada linha, o último commit que a alterou, o autor e a data. O nome soa acusatório, mas na prática é uma ferramenta para achar contexto: encontrar o commit, ler a mensagem e entender por que foi feito assim.

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60 — só um intervalo de linhas; também dá para usar -L :nome_da_funcao.
  • -w — ignorar alterações de espaços, para não cair em commits de formatação.
  • -C — rastrear linhas movidas de outros arquivos.
  • --ignore-rev <hash> ou o arquivo .git-blame-ignore-revs — pular commits em massa, como os de formatação automática.

Roteiro típico de investigação: o git blame encontra o commit, o git show mostra ele inteiro e o git log do arquivo dá as alterações vizinhas.

Não é só por hash que se referencia um commit. HEAD~1 é o pai do commit atual, HEAD~3 o bisavô. HEAD^2 é o segundo pai de um commit de merge. Nomes de branches, tags e branches remotas também funcionam: origin/main~2. Para ver o projeto inteiro num commit antigo, use git switch --detach <hash>; para voltar, git switch -.

Histórico bom e histórico ruim

Todos esses comandos só são tão úteis quanto o histórico é significativo. Mensagens como "fix", "wip", "mais ajustes" tornam o git log --grep e o git blame inúteis. Um bom commit é uma única alteração lógica com um título que explica o quê e por quê: fix: timeout da API aumentado para 30 s por causa do gateway lento. Daqui a seis meses, é exatamente esse commit que o blame vai encontrar, economizando uma hora sua.

Prática: investigando um bug pelo histórico

Suponha que, depois do último release, as requisições à API começaram a falhar por timeout. Veja como a combinação de comandos leva à causa em poucos minutos.

  1. Vemos o que entrou no release: git log v1.4.0..v1.5.0 --oneline. A lista é curta, mas pelos títulos o culpado não é óbvio.
  2. Filtramos pelo arquivo: git log v1.4.0..v1.5.0 --oneline -- src/api/. Restam dois commits.
  3. Buscamos no código: git log -S "timeout" --oneline -- src/api/ encontra o commit em que o valor do timeout mudou.
  4. Vemos o commit inteiro: git show 1c02e8f. O diff mostra que o timeout foi reduzido de 30 para 5 segundos, e a mensagem explica: "acelerando a resposta da UI".
  5. Conferimos quem mais mexeu nessa linha: git blame -L :build_session src/api/client.py.

Daí em diante, a decisão é de engenharia: restaurar o valor, mover o timeout para as configurações ou desfazer o commit com git revert. Já se os commits forem centenas e não der para achar o culpado no olho, entra em cena o git bisect — uma busca binária no histórico que, em poucos passos, aponta o commit que quebrou o comportamento.

Configurações que facilitam a vida

git config --global log.date iso            # formato das datas no log
git config --global diff.colorMoved zebra   # destacar linhas movidas no diff
git config --global core.pager "less -FRX"  # não abrir o paginador para saídas curtas

Se a saída vai ser processada por um script, desative as cores e o paginador: git --no-pager log --format="%H %s" --no-color. Para processamento automático, use o hash completo %H: com o tempo, prefixos curtos podem ficar ambíguos num repositório grande.

Resumo

O git log com os filtros --oneline, --graph, --author, -S e caminhos responde à pergunta "o que aconteceu". O git diff compara a pasta de trabalho, o índice e os commits — o importante é lembrar o que ele compara por padrão. O git show revela um commit ou uma versão antiga de um arquivo, e o git blame leva de uma linha de código à decisão que a originou. A leitura do histórico e a navegação pelos commits são praticadas no curso de Git.

Perguntas frequentes

Como sair do git log?

Pressione q — a saída está aberta no paginador less; para imprimir sem paginador, use git --no-pager log ou a flag -n com um número pequeno.

Como ver o histórico de um arquivo apagado?

Execute git log --oneline -- caminho/do/arquivo (com o traço duplo), e para ver o conteúdo antes da exclusão, git show &lt;hash&gt;^:caminho/do/arquivo.

Como comparar a branch local com a remota?

Primeiro git fetch, depois git diff origin/main ou git log origin/main..HEAD, para ver os seus commits ainda não enviados.

Existe uma visualização gráfica do histórico?

Sim, o Git vem com o gitk, e o grafo do histórico também está embutido no VS Code, nas IDEs JetBrains e nas interfaces web do GitHub e do GitLab.

Por que o git diff não mostra nada?

Provavelmente as alterações já foram adicionadas ao índice com git add — use git diff --staged; arquivos novos não rastreados o git diff não mostra de jeito nenhum.

Aprenda este tema em vídeo

Este tema é abordado em profundidade, com prática, no curso “Git do zero ao desenvolvedor confiante”.

Ir para o curso