Desenvolvimento

22 mai, 2012

Dica Git da semana: Cherry Picking

Publicidade

A dica Git desta semana é sobre puxar mudanças de um branch para outro, chamada de cherry picking.

Escolhendo mudanças

Cada commit em um repositório corresponde a uma tree cheia de arquivos. Normalmente, esses arquivos foram criados ao longo de vários commits. Mas, às vezes, é necessário levar o delta entre dois commits, e aplicá-lo a um branch diferente.

Um caso comum em que isso ocorre é quando um problema foi identificado e posteriormente corrigido, mas precisa portar para um branch de versão anterior.

Nesse caso, você não quer pegar o estado atual da tree (que pode ter alterações inacabadas ou não testadas); você só quer pegar o delta associado a essa mudança.

Em outros sistemas de controle de versão, você teria apenas que criar um diff com base na mudança mais recente, e depois corrigir a mudança em seu branch de lançamento. Em vez disso, com o Git, podemos usar o comando cherry-pick para fazer o trabalho para nós:

$ git checkout master
$ echo Working >> file.txt
$ git commit -m "Working" file.txt
$ echo BugFix >> bugfix.txt
$ git commit -m "BugFix" bugfix.txt
$ echo More Working >> file.txt
$ git commit -m "More working" file.txt
# We want to apply 'bugfix' to release
$ git checkout release10
$ git cherry-pick master~1
[release10 41037ab] BugFix
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bugfix.txt

Isso nos permitiu fazer uma única alteração – descrita aqui com master~1 – e copiar o delta no branch de lançamento.

Conjuntos de alterações

Podemos escolher conjuntos de commit (intervalos de revisões) para escolher se quisermos. Se tivéssemos várias mudanças, poderíamos ter master~3..master~1. Ao contrário de apenas gerar um diff e patch da tree atual, isso vai copiar os commits (e suas relações) sobre o novo branch.

Na verdade, já vimos o pick em uso, quando abordamos rebasing na semana passada. Quando você cria uma série de comandos para rebasing, você está dando-lhe instruções para escolher ou editar as alterações existentes:

@ edit 7bf9271 Typo
@ pick 756281e First
@ fixup 07e9061 First
@ pick 13aba60 Second

O “pick” aqui significa o mesmo que “git cherry-puck” para a mudança única. Na verdade, “edit” é realmente um atalho para “git cherry-pick -e”, e “fixup” e “squash” são atalhos para o git cherry-pick -n.

Origem da mudança

Finalmente, é interessante notar que, quando você copia uma mudança usando esse mecanismo, o hash de commit vai mudar (notavelmente porque terá uma hierarquia diferente).

Às vezes, isso não importa, mas se você deseja gravar onde a mudança original veio, você pode executar git cherry-pick-x. Isso insere uma mensagem de commit indicando de onde a mudança original veio:

# From example above
$ git checkout release10
$ git cherry-pick -x master~1
$ git cherry-pick master~1
[release10 41037ab] BugFix (cherry picked from commit 938a4c0bbb3985524192aa8a926ea6757263e94b)
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bugfix.txt

No entanto, note que isso geralmente só faz sentido se a mudança que está sendo pesquisada é de um branch público (para que a alteração de referência seja visível). Outra forma de representar essa mudança é a criação de um merge node entre o branch de liberação e o branch de desenvolvimento em curso como uma forma de mostrar que a fusão ocorreu.

Criando um novo histórico

Sempre que você está usando o cherry-pick, principalmente se você estiver reordenando commits, você está criando um novo histórico. No entanto, você nunca realmente joga fora o antigo, tudo está disponível a partir dos reflogs. Você não está destruindo o histórico, você está criando outros alternativos. Todo o cherry picking te dá a capacidade de aplicar os patches de outros branches de uma maneira segura e com menos erros.

?

Texto original disponível em http://alblue.bandlem.com/2011/06/git-tip-of-week-cherry-picking.html