Cenário: Seu cliente utiliza um outro SCM, por exemplo, o Harvest, no projeto o qual você trabalha. Mas, você e sua equipe resolvem utilizar o Git. Eis que você faz uma série de scripts de automação para pegar o seu release no Git e entregá-lo ao Harvest. Bacana, não? Para que isso funcione perfeitamente, você deve passar para o sistema de automação o nome dos arquivos que foram alterados, desse jeito, não será necessário enviar arquivos que sequer sofreram modificações, o que é bem interessante, diga-se de passagem.

Legal, existe o comando git whatchanged. Você pode passa como parâmetro o total de commits que você deseja analisar, utilizando a opção -n. Se você omití-lo, todas as modificações serão exibidas. (Se você informar o parâmetro -p, serão exibidas as modificações dentro dos arquivos).

Vamos dar uma olhada na saída desse comando:

$ git whatchanged -n 3
commit 8d726556aec75e1d6ef5ae477532fcc11770ac01
Author: Alberto Leal
Date:   Wed Jun 3 16:04:23 2009 -0400
 
Message 3
 
:100755 000000 0615380... 0000000... D  workspace/xxx/yyy/cfgXPTO.jnlp
:100755 000000 37076cc... 0000000... D  workspace/xxx/yyy/packageXYZ.jar
 
commit 3ab3a5e95fa031d8eb93154d161bfba228bc5f86
Author: Alberto Leal
Date:   Wed Jun 3 15:38:00 2009 -0400
 
Message 2
 
:100755 100755 849dc69... 1e7ef9d... M  workspace/xxx/src/com/xxx/yyy/ModelXYZ.java
:100755 100755 9828364... d85e5ee... M  workspace/xxx/WebContent/WEB-INF/jsp/viewXYZ.jsp
:000000 100755 0000000... d034c28... A  workspace/xxx/WebContent/htmlXPTO.html
 
commit 7e076b5130340f28e57526cf71ce96d7cc279538
Author: Alberto Leal
Date:   Wed Jun 3 10:04:56 2009 -0400
 
Message 1
 
:100755 100755 9c322de... 9828364... M  workspace/xxx/WebContent/WEB-INF/jsp/anotherXTPO.jsp

Repare que se você quiser pegar os arquivos modificados, você terá que copiar um a um. Trabalhoso, não? Existem diversas maneiras de se recuperar apenas os nomes dos arquivos. Uma sugestão seria:

def files_changed(commits, last_commit)
  File.open(commits, "r") do |infile|
  infile.each_line do |line|
    if line.include? last_commit
      break
    else
      er = line.match(/workspace(.*)/)
      puts er unless er.nil?
    end
  end
  end
end
 
files_changed(ARGV[0], ARGV[1])

Execute o seguinte comando no seu terminal para obter o resultado desejado:

$ git whatchanged > files.txt && ruby files_changed.rb files.txt 7e076b513

Se você quiser, simplesmente, pegar todos os arquivos modificado, você pode executar o comando abaixo:

$ git whatchanged | grep workspace | awk '{print($6)}'

Fica aí mais uma dica. Afinal, seria bem chato ter que copiar arquivo por arquivo =)