Git: Total de commits de cada commiter no projeto

Posted by Alberto Leal on June 3rd, 2009

Sua equipe utiliza Git na empresa? Você quer ver quem anda comitando mais?

Algumas pessoas me perguntaram como fazer para obter tal resultado. Há algum tempo eu twittei sobre isso.

Para aqueles que acompanham o meu blog, mas não me acompanham no twitter, aí vai a dica. A maneira de ver o total de commits de cada commiter em um projeto que utiliza o Git, como controlador de versão, é:

1
git shortlog -s -n --all

(O tweet está aqui.)

Ok. Mas agora você quer ver o total de commits apenas nos repositórios remotos? O comando é:

1
git rev-list --remotes --pretty=short

(O tweet está aqui.)

GIT: Visualizando as modificações nos commits

Posted by Alberto Leal on June 2nd, 2009

Cenário: Você trabalhou durante dias em um branch. Fez vários commits nele. E…., após algumas discussões, ficou decidido que algumas das suas modificações não entrarão na próxima build. A idéia das mensagens ao se fazer um commit é ajudar na identificação daquele commit específico.  Você pode analisar estas mensagens e remover alguns commits com base em tais mensagens. Mas, às vezes, só isso não basta para você. Você quer analisar antes alguns commits para ter certeza de que somente as alterações desejáveis, sejam adicionadas na build. Comando: git whatchanged Ps: As mensagens foram alteradas propositalmente. Utilize mensagens significativas em seus commits.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
commit d9a472455d9f91c75465af9778f5271baf532813
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Thu May 28 14:14:39 2009 -0400
 
    Message 7
 
commit 6251f4b532d0c602e41742ab6399b637b14596c8
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Wed May 27 15:51:56 2009 -0400
 
    Message 6
 
commit e71160c9fc1f676e94c4fe732f169e153731bf4c
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Tue May 26 13:18:03 2009 -0400
 
    Message 5
 
commit e91d5a2171f8a4edcb60004967bad847339046d8
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Thu May 21 15:31:49 2009 -0400
 
    Message 4
 
commit b514e967f01f579faab27f84017897d017810038
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Thu May 21 10:23:50 2009 -0400
 
    Message 3
 
commit c59d02c18bfeff297f91fc2f06247e82ff77b741
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Tue May 19 09:18:37 2009 -0400
 
    Message 2
 
commit 48b5d388ad78dbc260a3afd164c6b46cca7b9e51
Author: Alberto Alvine <albertonb@gmail.com>
Date:   Wed May 13 09:46:28 2009 -0400
 
    Message 1

Para visualizar quais foram as alterações em todos commits, execute git whatchanged -p. Esse comando mostrará os diffs de todos os arquivos que foram alterados. Se for desejável apenas visualizar os arquivos que sofreram alterações, execute apenas git whatchanged, sem parâmetro. Este comando foi útil para mim. Fica aí mais uma dica =) UPDATE 1: Esqueci de mencionar: Na hora de executar o git revert, você deve executá-lo de forma inversa, isto é,  vamos imaginar que você deseja desfazer os 2 últimos commits, o primeiro revert vai ser para o último commit, e o segundo revert para o penúltimo commit.

GIT: Quebrando um commit e cancelando algumas alterações

Posted by Alberto Leal on May 23rd, 2009

Dando sequência aos posts sobre GIT, aí vai mais uma dica: Como quebrar um commit e cancelar algumas alterações.

Assim como os posts anteriores, esse post foi inspirado em um problema que o meu time enfrentou semana passada.

Cenário: Foi feito o push de um commit contendo várias alterações no código. Porém, após ter sido feito o code review foi detectado que algumas mudanças não seriam mais necessárias, e/ou deveriam ser implementadas de outra forma. Claro que seria possível ir no código fonte e ir apagando todas as alterações que foram feitas. Mas, será que essa “limpeza” sairia às mil maravilhas? Será que o código voltaria a ficar da mesma forma que antes das alterações terem sido feitas? Acho difícil!

Elaborei um pequeno exemplo, apenas, para tentar ilustrar o cenário acima.

Temos os seguintes commits em nosso Projeto:

picture-22

picture-23

Repare que foi criado um branch para resolver um defeito, no nosso caso, foi adicionar um novo campo, País. Mas por algum motivo o registro de idade foi alterado acidentalmente.

No caso acima, é fácil ir ao arquivo e desfazer as alteração incorreta no campo “idade” antes de fazer o rebase/merge, eu sei. Mas, tente imaginar códigos reais, complexos, onde voltar ao código fonte e desfazer as alterações não seria a melhor solução =)

Uma solução para trazer todas as alterações e escolher o que vai ser efetivado para o merge/rebase é trazer o commit de volta para o stage do git para trabalhar nas alterações. Para isso, vamos utilizar o comando git format-patch para recuperar os commits. Em seguida, criaremos um novo branch para trabalharmos nas modificações e finalmente fazer o rebase com o branch master:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Alberto:ProjectX Alberto$ git branch
* Defect123
  master
Alberto:ProjectX Alberto$ git status
# On branch master
nothing to commit (working directory clean)
 
Alberto:ProjectX Alberto$ git log
commit ea4f2953c305b0453fd20f27b3043ebf96d541df
Author: Alberto Leal <albertonb@gmail.com>
Date:   Sat May 23 15:42:16 2009 -0300
 
    Adding new fields
 
commit 656236111360762d92f9efacb05e27b5cd067a04
Author: Alberto Leal <albertonb@gmail.com>
Date:   Sat May 23 15:41:35 2009 -0300
 
    Some new changes
 
commit 131519b37c1d1415e962d6fd23d4058c93438870
Author: Alberto Leal <albertonb@gmail.com>
Date:   Sat May 23 15:40:40 2009 -0300
 
    Initial Commit
Alberto:ProjectX Alberto$ git format-patch master
0001-Some-new-changes.patch
0002-Adding-new-fields.patch

Repare que os patches foram gerados  a partir do Defect123 em relação ao branch master, ou seja, somente as diferenças entre eles.

Para escolher quais as modificações vão entrar para fazer o merge/rebase com o master, é necessário que se crie um novo branch a partir do master - limpo, sem as modicações de Defect123 e use o comando git apply para aplicar os patches no stage.  Agora que os patches com os últimos commits já foram gerados, chegou a hora de jogá-los novamente no stage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Alberto:ProjectX Alberto$ git checkout master
Switched to branch "master"
Alberto:ProjectX Alberto$ git checkout -b Defect123_Changes
Switched to a new branch "Defect123_Changes"
Alberto:ProjectX Alberto$ git apply 0001-Some-new-changes.patch
Alberto:ProjectX Alberto$ git apply 0002-Adding-new-fields.patch
Alberto:ProjectX Alberto$ git log
commit 131519b37c1d1415e962d6fd23d4058c93438870
Author: Alberto Leal &lt;albertonb@gmail.com&gt;
Date:   Sat May 23 15:40:40 2009 -0300
 
    Initial Commit
Alberto:ProjectX Alberto$ git status
# On branch Defect123_Changes
# Changed but not updated:
#   (use "git add &lt;file&gt;..." to update what will be committed)
#
#       modified:   config.txt
#
# Untracked files:
#   (use "git add &lt;file&gt;..." to include in what will be committed)
#
#       0001-Some-new-changes.patch
#       0002-Adding-new-fields.patch
no changes added to commit (use "git add" and/or "git commit -a")

Veja que o arquivo config.txt foi alterado. Agora, vamos adicionar as alterações para serem comitadas, mas para isso vamos utilizar o comando git add -p (similar ao add interativo):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Alberto:ProjectX Alberto$ git add -p config.txt
diff --git a/config.txt b/config.txt
index ac82771..b36405c 100644
--- a/config.txt
+++ b/config.txt
@@ -1,6 +1,8 @@
 Nome: Alberto Leal
-email: albertonb@gmail.com
-idade: 24
+Email: albertonb@gmail.com
+Idade: 2423434
 Empresa: IBM
+Telefone: 12-1234-5678
+País: Brasil
 Sexo: Masculino
 Estado civil: solteiro
Stage this hunk [y/n/a/d/s/?]? s
Split into 2 hunks.
@@ -1,4 +1,4 @@
 Nome: Alberto Leal
-email: albertonb@gmail.com
-idade: 24
+Email: albertonb@gmail.com
+Idade: 2423434
 Empresa: IBM
Stage this hunk [y/n/a/d/j/J/?]? n
@@ -4,3 +4,5 @@
 Empresa: IBM
+Telefone: 12-1234-5678
+País: Brasil
 Sexo: Masculino
 Estado civil: solteiro
Stage this hunk [y/n/a/d/K/?]? y

Utilizando o comando acima, podemos quebrar as alterações feitas no arquivo utilizando a opção “s” (split). Após, você informa se deseja adicionar os fragmentos ao stage, utilizando as opções “y”- yes e “n”- no. Todos os fragmentos que você desejar adicionar no stage para comitá-lo, utilize a opção “y”. No pequeno exemplo acima, apenas foi mantido no commit a adição dos novos campos: Telefone e País. A alteração equivocada no campo “idade”foi eliminada do commit. Só nos resta efetivar as alterações comitando as mundanças:

1
2
3
4
5
6
7
8
9
10
11
12
13
Alberto:ProjectX Alberto$ git commit -m 'Cutting branch'
Created commit 9e365a2: Cutting branch
 1 files changed, 2 insertions(+), 0 deletions(-)
Alberto:ProjectX Alberto$ git checkout config.txt
Alberto:ProjectX Alberto$ cat config.txt
Nome: Alberto Leal
email: albertonb@gmail.com
idade: 24
Empresa: IBM
Telefone: 12-1234-5678
País: Brasil
Sexo: Masculino
Estado civil: solteiro

Cuidado para não adicionar o arquivo novamente ao stage (git add config.txt). As alterações que você fez já estão lá, prontas para serem comitadass. Se você se esquecer e adicionar o arquivo novamente ao stage, você perderá todas as mudanças que você fez no add interativo. É aconselhável que, logo após o comando git commit, você execute git checkout <file>, como mostrado acima. Desse jeito, você pegará o arquivo que está no repositório atualizado.

picture-24

Agora, só nos resta fazer o rebase com o branch principal:

1
2
3
4
5
Alberto:ProjectX Alberto$ git checkout master
Switched to branch "master"
Alberto:ProjectX Alberto$ git rebase Defect123_Changes
First, rewinding head to replay your work on top of it...
Fast-forwarded master to Defect123_Changes.

picture-25

É isso pessoal! Espero que a técnica apresentada nesse post lhe seja útil algum dia, assim como foi para mim.

Abraços!

Juntando vários commits no Git

Posted by Alberto Leal on May 21st, 2009

Foi no ano passado que comecei a utilizar o GIT como VCS padrão. Naquela ocasião, não tinha  muitos problemas de conflitos, já que o “time” era pequeno - só eu =)

Hoje, faço parte de um time de 8 desenvolvedores. Já dá para imaginar que problemas na hora de fazer o rebase/merge já começam a aparecer com uma certa frequência. É gente comitando o dia inteiro!

Quando alguém no time cria um branch remoto, e trabalha nele o dia inteiro, por exemplo, ao final do dia é possível existir uma quantidade de commits consideráveis. Mas, na hora de enviar essas alterações para o repositório - git push - pode não ser necessário enviar todo aquele histórico de commits, apenas o resultado final interessa. Mas, dá para fazer isso? A resposta é: Sim, dá!

Mas atenção, somente faça isso em commits que ainda não foram enviados para o repositório externo. Pois se isso já tiver acontecido, outro desenvolvedor pode ter feito outras alterações e os conflitos aparecerão para lhe trazer dor de cabeça.

A idéia é utilizar git rebase –interactive, ou simplesmente git rebase -i.

Imagine o seguinte cenário: Você precisa trabalhar em um defect, e para isso você cria um branch para trabalhar nele. Ao longo do seu trabalho, você vai fazendo vários commits para manter o status do seu trabalho, já que de vez enquando você precisa pular para outro branch para resolver outra coisa, ou simplesmente testar alguma funcionalidade em outro branch que seu chefe lhe pediu (E, dependendo da situação, utilizar git stash não é a solução). Na hora de fazer o push, você só precisa enviar o defect resolvido. Se você desejar juntar todos os commits em um único commit que represente aquele seu defect, siga os passos abaixo:

picture-8

Veja que temos 4 commits em nosso repositório. E desejamos unir os três últimos commits. Para isso, vamos utilizar o comando que foi citado anteriormente:

picture-14

git rebase -i master~3

O comando acima diz para fazer o rebase interativo de 3 commits a partir do master. Feito isso, será aberto um editor para que você faça as devidas alterações:

picture-16

Marque os últimos commits que você deseja juntar com o primeiro com a palavra squash. Feito isso, salve o documento e um novo editor será aberto para que você informe a mensagem para esse novo commit.  No exemplo abaixo, eu deixei as mensagens de todos os commits, mas é permitido que você informe a mensagem que desejar.

picture-18Observe que, agora temos apenas 2 commits, ao invés de 4:

picture-191

Bastante útil. Mas, use apenas se você realmente não precisar do histórico desses commits.

UPDATE 1: Execute git rebase –continue para consolidar as alterações.

Alterando a mensagem de um commit no GIT

Posted by Alberto Leal on May 20th, 2009

Se você, assim como eu, já precisou alterar a mensagem de um commit no git, aí vai uma dica:

Antes, uma observação: se você já fez o push do commit que você deseja alterar a mensagem, não faça nenhuma alteração! Isso pode causar uma série de conflitos com os demais abaixo do seu commit.

Alterando a mensagem

Primeiro, é necessário escolher um commit abaixo daquele que será alterado. Para isso, dê um git log para listar os commits:

git log

Feito isso, escolha o commit, o qual a partir dele os commits acima poderão ser alterados e dê um git rebase -i <commit>:

picture-7git rebase -i 24eb338

Com o editor aberto, marque com a palavra EDIT os commits que você deseja alterar. Salve o arquivo e feche o editor:

picture-10

Agora, para abrir o editor e alterar os commits que você marcou como EDIT, execute git commit –amend:

picture-11

picture-13

Altere a mensagem do commit e está pronto!

Observe que o commit agora tem outro hash - dê git log para visualizar a alteração-, pois, essa tarefa de alterar a mensagem de um commit faz com que o GIT gere um novo commit.

Controle de versão com Subversion

Posted by Alberto on May 19th, 2008

Há alguns meses atrás eu tive uma grande necessidade de organizar as versões de uma aplicação. Simplesmente porque a situação já não estava “legal”. O que quero dizer é que haviam arquivos e mais arquivos de backup, e no final das contas era praticamente impossível saber qual era a última versão que funcionava.

Uma forma de minimizar esses tipos de problemas é utilizar uma ferramenta de controle de versão. A ferramenta que venho utilizando chama-se SUBVERSION.

O que é um software de controle de versão? E, para que serve? (Wikipédia)

“Um sistema de controle de versão é um software com a finalidade de gerenciar diferentes versões no desenvolvimento de um documento qualquer. Esses sistemas são comumente utilizados no desenvolvimento de software para controlar as diferentes versões – histórico e desenvolvimento – dos códigos-fontes e também da documentação.”

Antes de ver como utilizar a ferramenta, vamos ver alguns conceitos importantes:

  • Repositório: Local onde o(s) projeto(s) será(ão) armazenado(s).
  • Trunk: Diretório onde se encontrará o projeto em fase de desenvolvimento (Dia a dia). O desenvolvimento do projeto começa aqui dentro.
  • Branch: Diretório destinado às fases de testes. Vamos supor o seguinte cenário, enquanto a Equipe A trabalha no desenvolvimento de novas funcionalidades da versão 1.0 do projeto, a Equipe B já inicia alguns testes para adicionar na versão 2.0 do projeto. Este projeto é de grande importância. Tudo o que for feito como forma de testar algo, sem comprometer o projeto como um todo, deverá ser colocado dentro deste diretório.
  • Tags: Diretório destinado às releases do projeto. Sempre que novas funcionalidades são adicionadas ao projeto e/ou bugs são corrigidos novas versões surgem dentro do diretório TAGS.

Sempre que se cria uma nova release, todo o projeto que se encontra em trunk é copiado para tags. É legal saber que, os arquivos não são copiados literalmente sempre que uma nova release é lançada. O subversion controla os arquivos e copia apenas os arquivos que sofreram alterações, isto é, arquivos que não sofreram modificações são linkados internamente dentro da nova release, fazendo com que o número de arquivos repetidos dentro do seu repositório seja mínimo.
Read the rest of this entry »


Copyright © 2007 Alberto Leal. All rights reserved.