Git
Chapters ▾ 2nd Edition

2.3 Fundamentos de Git - Vendo o histórico de Commits

Vendo o histórico de Commits

Depois de você ter criado vários commits, ou se você clonou um repositório com um histórico de commits pré-existente, você vai provavelmente querer olhar para trás e ver o que aconteceu. A ferramenta mais básica e poderosa para fazer isso é o comando git log.

Esses exemplos usam um projeto muito simples chamando “simplegit”. Para conseguir o projeto, execute

$ git clone https://github.com/schacon/simplegit-progit

Quando você executa git log neste projeto, você deve receber um retorno que se parece com algo assim:

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

Por padrão, sem argumentos, git log lista os commits feitos neste repositório em ordem cronológica inversa; isto é, o commit mais recente aparece primeiro. Como você pode ver, esse comando lista cada commit com o seu checksum SHA-1, o nome e email do autor, data de inserção, e a mensagem do commit.

Está disponível um enorme número e variedade de opções para o comando git log a fim de lhe mostrar exatamente aquilo pelo que está procurando. Aqui, vamos mostrar a você algumas das mais populares.

Uma das opções que mais ajuda é -p, que mostra as diferenças introduzidas em cada commit. Você pode também usar -2, que lista no retorno apenas os dois últimos itens:

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.platform  =   Gem::Platform::RUBY
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com"
     s.summary   =   "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end
\ No newline at end of file

Essa opção mostrar a mesma informação mas com um diff diretamente após cada item. Isso é de muita ajuda para revisão de código ou para rapidamente procurar o que aconteceu durante uma série de commits que uma colaborador tenha adicionado. Você pode também usar uma série de opções resumidas com o git log. Por exemplo, se você quer ver algumas estatísticas abreviadas para cada commit, você pode usar a opção --stat:

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

 README           |  6 ++++++
 Rakefile         | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

Como você pode ver, a opção --stat apresenta abaixo de cada commit uma lista dos arquivos modificados, quantos arquivos foram modificados, e quantas linhas nestes arquivos foram adicionadas e removidas. Por último ela também colocar um resumo das informações.

Uma outra opção realmente muito util é --pretty. Essa opção modifica os registros retornados para formar outro formato diferente do padrão. Algumas opções pré-definidas estão disponíveis para você usar. A opção oneline mostra cada commit em uma única linha, esta é de muita ajuda se você está olhando para muitos commits. Em adição, as opções short, full, e fuller apresentam o retorno quase no mesmo formato porem com menos ou mais informações, respectivamente:

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

A opção mais interessante é format, a qual permite a você especificar seu próprio formato de registros de retorno. Isso é especialmente útil quando você esta gerando um retorno para uma máquina analisar – pois você especifica o formato explicitamente, você sabe que isso não irá mudar com as atualizações do Git:

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit

Useful options for git log --pretty=format lista algumas das opções mais uteis que format gera.

Table 1. Useful options for git log --pretty=format
Option Description of Output

%H

Commit hash

%h

Abbreviated commit hash

%T

Tree hash

%t

Abbreviated tree hash

%P

Parent hashes

%p

Abbreviated parent hashes

%an

Author name

%ae

Author email

%ad

Author date (format respects the --date=option)

%ar

Author date, relative

%cn

Committer name

%ce

Committer email

%cd

Committer date

%cr

Committer date, relative

%s

Subject

Você talvez esteja imaginando qual a diferença entre author e committer. O autor é a pessoa que escreveu originalmente o trabalho, ao passo que a pessoa que submeteu o trabalho é o committer. Então, se você criar uma correção para um projeto e um dos membros principais submete a correção, ambos receberão crédito – você como autor, e o membro principal como commiter. Nós vamos abordar esta distinção um pouco mais em [ch05-distributed-git].

As opções oneline e format são particularmente úteis juntamente com uma outra opção de log chamada --graph. Esta opção adiciona um pequeno gráfico ASCII mostrando seu histórico de branch e merge:

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
*  11d191e Merge branch 'defunkt' into local

Esse tipo de retorno se tornará mais interessante conforme formos criando branches e merges no próximo capitulo.

Essas são apenas algumas opções simples de formatações de retorno para git log – existem muitas mais. Common options to git log lista as opções que nós já abordamos, assim como algumas outras opções de formatação mais comuns que talvez sejam muito úteis, juntamente com o como ela mudam o retorno do comando log.

Table 2. Common options to git log
Option Description

-p

Show the patch introduced with each commit.

--stat

Show statistics for files modified in each commit.

--shortstat

Display only the changed/insertions/deletions line from the --stat command.

--name-only

Show the list of files modified after the commit information.

--name-status

Show the list of files affected with added/modified/deleted information as well.

--abbrev-commit

Show only the first few characters of the SHA-1 checksum instead of all 40.

--relative-date

Display the date in a relative format (for example, “2 weeks ago”) instead of using the full date format.

--graph

Display an ASCII graph of the branch and merge history beside the log output.

--pretty

Show commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format).

Limitando o retorno do comando Log

Em adição ás opções de formatação do retorno, git log leva um número útil de opções de limitação – que são, opções que lhe permitem mostrar apenas um subconjunto de commits. Você já viu essa opção antes – a opção -2, a qual mostra apenas os dois últimos commits. De fato, você pode usar -<n>, onde n é qualquer número inteiro para mostra os ultimos n commits. Na verdade, você não gostará de usar isso frequentemente, pois o Git por padrão enquadra todo o retorno através de uma página então você vê apenas uma página de registros por vez.

Entretanto, as opções de lina do tempo tais como --since e --until são muito uteis. Por exemplo, esse comando retorna a lista de commits feitos nas últimas duas semanas:

$ git log --since=2.weeks

Esse comando funciona com um grande número de formatos – você pode determinar uma data específica como "2008-01-15", ou uma data relativa tal como "2 anos 1 dia 3 minutos atrás".

Você pode também filtrar a lista de commits que combinam com algum critério de busca. A opção --author permite você filtrar por um autor especifico, e a opção --grep permite você procurar por palavras chaves na mensagem do commit. (Note que se você quer especificar ambas as opções autor e grep, você tem que adicionar --all-match ou o comando irá combinar com qualquer uma delas.)

Uma outra opção de filtro que realmente ajuda muito é -S A qual pega um conjunto de caracteres e mostra apenas os commits que introduzem uma mudança no código onde esse conjunto é adicionado ou removido. Por exemplo, se você quer encontrar o último commit que adicionou ou removeu uma referência a uma função especifica, você poderia chamar:

$ git log -Sfunction_name

A última opção realmente útil para passar ao git log como filtro é o caminho. Se você especificar um diretório ou nome de arquivo, você pode limitar os registros retornados referentes aos commits que introduziram uma mudança a estes arquivos. Issa é sempre a última opção e é geralmente precedida por dois traços (--) para separa os caminhos das opções dos comandos.

Em Options to limit the output of git log nós vamos listar estes e algumas outras opções comuns para sua referência.

Table 3. Options to limit the output of git log
Option Description

-(n)

Show only the last n commits

--since, --after

Limit the commits to those made after the specified date.

--until, --before

Limit the commits to those made before the specified date.

--author

Only show commits in which the author entry matches the specified string.

--committer

Only show commits in which the committer entry matches the specified string.

--grep

Only show commits with a commit message containing the string

-S

Only show commits adding or removing code matching the string

Por exemplo, se você quer ver quais commits estão modificando arquivos de testes no histórico do código fonte do Git que sofreram commit por Junio Hamano no mês de Outubro de 2008 e não são commits de merge, você pode executar algo semelhante a isso:

$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
   --before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch

Dos quase 40.000 commits no histórico do código fonte do Git, esse comando mostra os 6 que combinam com esses critérios.