Olhando o histórico com Git

Uma atividade comum no dia a dia é olhar o histórico do controle de versão, onde buscamos números de atividades, assim como as alterações introduzidas por um commit. Assim pretendo mostrar alguns comandos que podem ser úteis e que poderemos usar no dia-a-dia.

Todos os comandos foram executados no repositório deste blog

git log

Com o git log é possível listar os commits em um branch, assim como filtrar por autor, data, entre outros campos.

O primeiro parâmetro útil do comando é o -n, que limita o número de commits no log.

$ git log -n 5

commit cceeefec36d9eb0461d84d59d6d5ac3e8ad7bc5a (HEAD -> master, origin/master, origin/HEAD)
Author: João Vitor Retamero
Date: Tue Jul 9 10:41:34 2019 -0300

Remoção de projetos

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

commit 1a8dc6d8bace25d78dfdb2821f47de06fb9d15d1
Author: João Vitor Retamero
Date: Tue Jul 9 10:37:03 2019 -0300

Rascunhos

commit 4c9459ef22dae67937c202ddff51e45f32703a22
Author: João Vitor Retamero
Date: Mon Jul 1 22:07:42 2019 -0300

Elisa - Geração de código

commit 0bbb2c70702fe8d38b129a8f6fb42819e6d4479b
Author: João Vitor Retamero
Date: Wed May 29 22:46:39 2019 -0300

Elisa

Se quiser uma versão mais compacta do resultado, pode utilizar o argumento --oneline, mas isto só mostrará o início do hash e a mensagem do commit.

$ git log -n 5 --oneline

cceeefe (HEAD -> master, origin/master, origin/HEAD) Remoção de projetos
3cc15a0 Configuração SEO e remoção de lista de projetos
1a8dc6d Rascunhos
4c9459e Elisa - Geração de código
0bbb2c7 Elisa

Agora imagine que você precise filtrar os commits que fiz para o exame 70-483. O parâmetro --grep=<padrão> nos permite buscar um texto nas mensagens dos commits.

O valor de <padrão> pode ser uma expressão regular, portanto você pode realizar filtros mais sofisticados se precisar.

$ git log -n 5 --grep=70-483

commit 9588d9603169d5c226b74dfef792ea8fb92c2a2f
Author: João Vitor Retamero
Date: Sat Jan 26 23:50:14 2019 -0200

70-483 - Research about indexers and started research about IUnknown

commit d407321ba7d73ad9a743a66f9081e243cae42e80
Author: João Vitor Retamero
Date: Sat Jan 26 23:09:03 2019 -0200

70-483

commit 2fb8c793bff2683f7058a8fc773f67013ca2c936
Author: João Vitor Retamero
Date: Sat Jan 26 23:05:24 2019 -0200

70-483 renamed to have date

commit 5a6774ef9a446e3d2520c4d050fb4dbf03702d5e
Author: João Vitor Retamero
Date: Sat Jan 26 22:54:23 2019 -0200

Publish 70-483 annotations

commit 3fab03d2d481b4cda3147e4822dd960bfbc7bb05
Author: João Vitor Retamero
Date: Sun Jan 20 11:00:30 2019 -0200

70-483

Muitas vezes queremos ver commits a partir de uma data, e para isso o parãmetro --since=<data> pode ajudar.

Para o valor de <data>, utilize a data no formato yyyy-MM-ddTHH:mm:ss.

$ git log --since=2019-07-09T00:00:00

commit cceeefec36d9eb0461d84d59d6d5ac3e8ad7bc5a (HEAD -> master, origin/master, origin/HEAD)
Author: João Vitor Retamero
Date: Tue Jul 9 10:41:34 2019 -0300

Remoção de projetos

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

commit 1a8dc6d8bace25d78dfdb2821f47de06fb9d15d1
Author: João Vitor Retamero
Date: Tue Jul 9 10:37:03 2019 -0300

Rascunhos

Como o git mostra os commits na ordem do mais recente para o mais antigo, podemos usar o parâmetro --reverse para inverter a ordem do resultado.

$ git log --since=2019-07-09T00:00:00 --reverse

commit 1a8dc6d8bace25d78dfdb2821f47de06fb9d15d1
Author: João Vitor Retamero
Date: Tue Jul 9 10:37:03 2019 -0300

Rascunhos

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

commit cceeefec36d9eb0461d84d59d6d5ac3e8ad7bc5a (HEAD -> master, origin/master, origin/HEAD)
Author: João Vitor Retamero
Date: Tue Jul 9 10:41:34 2019 -0300

Remoção de projetos

Já sabemos como filtrar a atividade e até como ordenar os resultados, mas como identificamos os arquivos que foram modificados?

O argumento --name-only lista o nome de todos os arquivos que fazem parte do commit.

$ git log -n 3 --name-only

commit cceeefec36d9eb0461d84d59d6d5ac3e8ad7bc5a
Author: João Vitor Retamero
Date: Tue Jul 9 10:41:34 2019 -0300

Remoção de projetos

_layouts/projeto.html
_projetos/hermes1.md
_projetos/hermes2.md
_projetos/popularmovies.md
img/projetos/hermes_1_00.png
img/projetos/hermes_1_01.png
img/projetos/hermes_1_02.png
img/projetos/hermes_1_03.png
img/projetos/hermes_1_04.png
img/projetos/hermes_2_00.png
img/projetos/hermes_2_01.png
img/projetos/hermes_2_02.png
img/projetos/hermes_2_03.png
img/projetos/hermes_2_04.png
img/projetos/hermes_2_05.png
img/projetos/hermes_2_06.png
img/projetos/pop_00.png
img/projetos/pop_01.png
img/projetos/pop_02.png
projetos/index.html

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

_config.yml

commit 1a8dc6d8bace25d78dfdb2821f47de06fb9d15d1
Author: João Vitor Retamero
Date: Tue Jul 9 10:37:03 2019 -0300

Rascunhos

_drafts/assemblies-net-core-mono-cecil.md
_drafts/csharp-e-tipos.md
_drafts/tres-arvores-git.md

Se precisar saber de quantos arquivos foram alterados, incluídos ou removidos, use o argumento --stat.

$ git log -n 3 --stat

commit cceeefec36d9eb0461d84d59d6d5ac3e8ad7bc5a
Author: João Vitor Retamero
Date: Tue Jul 9 10:41:34 2019 -0300

Remoção de projetos

_layouts/projeto.html | 18 ------------------
_projetos/hermes1.md | 18 ------------------
_projetos/hermes2.md | 19 -------------------
_projetos/popularmovies.md | 15 ---------------
img/projetos/hermes_1_00.png | Bin 9062 -> 0 bytes
img/projetos/hermes_1_01.png | Bin 10023 -> 0 bytes
img/projetos/hermes_1_02.png | Bin 14474 -> 0 bytes
img/projetos/hermes_1_03.png | Bin 10319 -> 0 bytes
img/projetos/hermes_1_04.png | Bin 7236 -> 0 bytes
img/projetos/hermes_2_00.png | Bin 7241 -> 0 bytes
img/projetos/hermes_2_01.png | Bin 64307 -> 0 bytes
img/projetos/hermes_2_02.png | Bin 14679 -> 0 bytes
img/projetos/hermes_2_03.png | Bin 8975 -> 0 bytes
img/projetos/hermes_2_04.png | Bin 17347 -> 0 bytes
img/projetos/hermes_2_05.png | Bin 11774 -> 0 bytes
img/projetos/hermes_2_06.png | Bin 13746 -> 0 bytes
img/projetos/pop_00.png | Bin 255147 -> 0 bytes
img/projetos/pop_01.png | Bin 177859 -> 0 bytes
img/projetos/pop_02.png | Bin 123061 -> 0 bytes
projetos/index.html | 17 -----------------
20 files changed, 87 deletions(-)

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

_config.yml | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)

commit 1a8dc6d8bace25d78dfdb2821f47de06fb9d15d1
Author: João Vitor Retamero
Date: Tue Jul 9 10:37:03 2019 -0300

Rascunhos

_drafts/assemblies-net-core-mono-cecil.md | 10 ++++++++++
_drafts/csharp-e-tipos.md | 9 ---------
_drafts/tres-arvores-git.md | 8 ++++++++
3 files changed, 18 insertions(+), 9 deletions(-)

Para identificar a alteração, podemos usar o argumento -p.

Alguns commits foram removidos para encurtar o post

$ git log -n 3 -p

commit 3cc15a084c29a4b0eff462c303161fd087a69694
Author: João Vitor Retamero
Date: Tue Jul 9 10:40:12 2019 -0300

Configuração SEO e remoção de lista de projetos

diff --git a/_config.yml b/_config.yml
index 519dd2e..79d08d7 100644
--- a/_config.yml
+++ b/_config.yml
@@ -1,6 +1,7 @@
permalink: '/:title'
title: João Vitor Retamero
url: 'http://joaoretamero.com.br'
+lang: pt-BR
encoding: utf-8
plugins:
- jekyll-paginate
@@ -11,14 +12,10 @@ paginate: 5
paginate_path: '/pagina/:num'
sass:
style: compressed
-collections:
- projetos:
- output: true
- permalink: '/projetos/:path'
author: João Vitor Retamero
twitter:
username: jvretamero
-logo: /images/foto.png
+logo: /img/foto.png
social:
name: João Vitor Retamero
links:

Como o resultado do comando pode ser muito grande, recomendo redirecionar o resultado para um arquivo com o >.

$ git log -n 3 -p > log.txt

git show

Já vimos como localizar alguns commits, agora podemos ver melhor o que foi modificado em um arquivo específico e até como este arquivo era antes do commit.

Em muitos casos teremos commits com vários arquivos alterados, então para ver um arquivo específico do commit é possível usar o git show <hash> -- <arquivo>. Como o comando mostra os dados completos do commit, pode-se usar o argumento --oneline para deixar o resultado menos verboso.

$ git show --oneline 3cc15a084c29a4b0eff462c303161fd087a69694 -- _config.yml

3cc15a0 Configuração SEO e remoção de lista de projetos
diff --git a/_config.yml b/_config.yml
index 519dd2e..79d08d7 100644
--- a/_config.yml
+++ b/_config.yml
@@ -1,6 +1,7 @@
permalink: '/:title'
title: João Vitor Retamero
url: 'http://joaoretamero.com.br'
+lang: pt-BR
encoding: utf-8
plugins:
- jekyll-paginate
@@ -11,14 +12,10 @@ paginate: 5
paginate_path: '/pagina/:num'
sass:
style: compressed
-collections:
- projetos:
- output: true
- permalink: '/projetos/:path'
author: João Vitor Retamero
twitter:
username: jvretamero
-logo: /images/foto.png
+logo: /img/foto.png
social:
name: João Vitor Retamero
links:

Bom, já sabemos o que foi alterado, mas e se precisarmos ver o arquivo completo antes deste commit? Com o show isto é possível e a sintaxe é git show <hash>~<qtde_revisoes>:<arquivo>.

Então o comando que podemos usar é o git show 3cc15a084c29a4b0eff462c303161fd087a69694~1:_config.yml que nos mostrará o arquivo completo antes daquele commit.

Algumas linhas foram omitidas para não deixar o texto muito extenso, mas é possível notar que a linha introduzida no commit não apareceu.

$ git show 3cc15a084c29a4b0eff462c303161fd087a69694~1:_config.yml

permalink: '/:title'
title: João Vitor Retamero
url: 'http://joaoretamero.com.br'
encoding: utf-8
plugins:
- jekyll-paginate
- jekyll-seo-tag
- jemoji
excerpt_separator:
paginate: 5
paginate_path: '/pagina/:num'
sass:
style: compressed
collections:
projetos:
output: true
permalink: '/projetos/:path'
author: João Vitor Retamero
twitter:
username: jvretamero
logo: /images/foto.png
social:
name: João Vitor Retamero
links:
- 'https://github.com/jvretamero'
- 'https://twitter.com/jvretamero'
- 'https://www.linkedin.com/in/jvretamero'
- 'http://stackoverflow.com/users/5554570/jvretamero'

git blame

Inúmeras vezes precisamos saber qual commit introduziu ou modificou determinado trecho de um arquivo. Então podemos usar o comando git blame -- <arquivo>, que irá gerar anotações no arquivo indicando o commit e o autor daquela linha.

$ git blame -- _config.yml

2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 1) permalink: '/:title'
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 2) title: João Vitor Retamero
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 3) url: 'http://joaoretamero.com.br'
3cc15a08 (João Vitor Retamero 2019-07-09 10:40:12 -0300 4) lang: pt-BR
^ce2adae (João Vitor 2016-01-31 18:51:10 -0200 5) encoding: utf-8
1178f341 (João Vitor Retamero 2018-01-01 13:25:26 -0200 6) plugins:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 7) - jekyll-paginate
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 8) - jekyll-seo-tag
dc42595a (João Vitor Retamero 2019-05-26 10:36:57 -0300 9) - jemoji
^ce2adae (João Vitor 2016-01-31 18:51:10 -0200 10) excerpt_separator:
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 11) paginate: 5
447f9eff (João Vitor Retamero 2017-11-27 00:13:19 -0200 12) paginate_path: '/pagina/:num'
c1db10fb (João Vitor 2016-07-07 23:09:22 -0300 13) sass:
c1db10fb (João Vitor 2016-07-07 23:09:22 -0300 14) style: compressed
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 15) author: João Vitor Retamero
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 16) twitter:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 17) username: jvretamero
3cc15a08 (João Vitor Retamero 2019-07-09 10:40:12 -0300 18) logo: /img/foto.png
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 19) social:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 20) name: João Vitor Retamero
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 21) links:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 22) - 'https://github.com/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 23) - 'https://twitter.com/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 24) - 'https://www.linkedin.com/in/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 25) - 'http://stackoverflow.com/users/5554570/jvretamero'

Note que o resultado é o hash do commit que introduziu/modificou a linha, seguido pelo autor, data e número da linha. Com o hash do commit, podemos aplicar os comandos conhecidos anteriormente neste texto.

Como o arquivo inteiro é anotado, podemos limitar o resultado por faixa de linhas com o argumento -L.

$ git blame -L 17,19 -- _config.yml

2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 17) username: jvretamero
3cc15a08 (João Vitor Retamero 2019-07-09 10:40:12 -0300 18) logo: /img/foto.png
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 19) social:

É importante lembrar que o comando da maneira que usamos, mostrará o último commit que você tiver no seu repositório local. Caso seja necessário anotar um arquivo antes de um commit, podemos passar o hash do commit como parâmetro.

$ git blame 3cc15a08~1 -- _config.yml

2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 1) permalink: '/:title'
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 2) title: João Vitor Retamero
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 3) url: 'http://joaoretamero.com.br'
^ce2adae (João Vitor 2016-01-31 18:51:10 -0200 4) encoding: utf-8
1178f341 (João Vitor Retamero 2018-01-01 13:25:26 -0200 5) plugins:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 6) - jekyll-paginate
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 7) - jekyll-seo-tag
dc42595a (João Vitor Retamero 2019-05-26 10:36:57 -0300 8) - jemoji
^ce2adae (João Vitor 2016-01-31 18:51:10 -0200 9) excerpt_separator:
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 10) paginate: 5
447f9eff (João Vitor Retamero 2017-11-27 00:13:19 -0200 11) paginate_path: '/pagina/:num'
c1db10fb (João Vitor 2016-07-07 23:09:22 -0300 12) sass:
c1db10fb (João Vitor 2016-07-07 23:09:22 -0300 13) style: compressed
b5b24d2e (João Vitor 2016-05-15 00:23:51 -0300 14) collections:
b5b24d2e (João Vitor 2016-05-15 00:23:51 -0300 15) projetos:
b5b24d2e (João Vitor 2016-05-15 00:23:51 -0300 16) output: true
4a78da50 (João Vitor Retamero 2017-11-26 23:58:30 -0200 17) permalink: '/projetos/:path'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 18) author: João Vitor Retamero
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 19) twitter:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 20) username: jvretamero
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 21) logo: /images/foto.png
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 22) social:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 23) name: João Vitor Retamero
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 24) links:
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 25) - 'https://github.com/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 26) - 'https://twitter.com/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 27) - 'https://www.linkedin.com/in/jvretamero'
2bc32527 (João Vitor Retamero 2017-12-31 19:29:37 -0200 28) - 'http://stackoverflow.com/users/5554570/jvretamero'

Conclusão

Neste post vimos alguns comandos básico para ver o histórico de um repositório no Git. A ferramenta tem comandos mais avançados, mas isso fica para um próximo post.

Até mais.