Black Belt Merging

Depois que você ficar confortável com the Savepoint pattern, você pode se cansar de ficar criando o branch de ponto de retorno, só para ter que lembrar de excluí-lo a cada vez. Se é assim, eu tenho boas notícias para você: na verdade você não precisa usar um branch como um ponto de retorno para merges.

Um commit de merge sempre termina com um rótulo de branch apontando para ele e um dos commits pai do branch vai ser o commit de onde esse rótulo de branch foi movido.

Você pode precisar ler essa frase algumas vezes para entendê-la. O resultado é que o commit de onde você começou—aquele que você teria marcado com um branch de retorno—sempre será alcançável.

Aí que está: o Git não liga para como você chama os seus branches. Lembre-se, os branches são apenas arquivos de 40 bytes no disco que apontam para o hash SHA-1 do commit, razão pela qual o Git realmente os usa para tudo. O branch na verdade só está la para que nós humanos molengas tenhamos um nome conveniente, memorável, apontando para uma parte do grafo.

Ao final de the Savepoint pattern, o comando que você digita para reiniciar o seu branch para o ponto de retorno é git reset --hard savepoint (onde "savepoint" é um nome de branch). Se você olhar a documentação que aparece quando você digita git reset -h, você verá que o argumento final que ele recebe se chama <commit>. Versões anteriores da documentação chamavam isso de <commit-ish>, o que era um lembrete conveniente de que você poderia usar qualquer coisa que o Git conseguisse transformar num hash SHA-1.

Coisas que o Git fica feliz em aceitar num argumento <commit> incluem (mas provavelmente não se limitam a):

  • Nomes de branches
  • Tags
  • Referências relativas como HEAD^, HEAD^^, or HEAD~3
  • hashes SHA-1 parciais como 8d434382 (você só precisa fornecer dígitos iniciais suficientes para que sejam únicos; o Git vai completar o resto para você)
  • hashes SHA-1 como 8d434382d9420940be260199a8a058cf468d9037 (esses são muito fáceis para o Git transformar em hashes SHA-1!)

Então, no final de the Savepoint pattern, se você realmente quer desfazer o merge, você pode simplesmente usar git log ou seu visualizador para descobrir o SHA-1 do commit (vamos dizer que comece com 1234abcd), e daí digitar isto:

git reset --hard 1234abcd

...e o Git se comportaria do mesmo jeito que quando você lembrou de criar um branch antes do merge.

Essa parte sobre "quando você lembrou de" me lembra: um dos comentários mais úteis que eu já li sobre o Git foi o The Thing About Git do Ryan Tomayko. (Sim, é o mesmo que eu citei no LSD and Chainsaws.)