Reescrevendo a história

Git é uma excelente ferramenta para o trabalho cooperativo. Ele pode fazer muitas coisas, mas é incapaz de resolver conflitos entre as pessoas. Afinal de contas, o Git é apenas um programa de computador e, enquanto não chega o dia da Strong AI, teremos que resolver os conflitos apenas entre nós, reles seres humanos.

A que tipo de conflito estou me referindo? Não estou falando de nada muito sério, como o que aconteceu aqui na Europa há 70 anos, mas apenas de situações que ocorrem quando dois colaboradores estão trabalhando concomitantemente em um projeto sob controle Git. Cada um faz modificações e commits do seu lado, partindo do mesmo ponto da história. Um deles é mais esperto e faz o git push primeiro. Quando o outro chega para fazer o seu push, o repositório remoto reclama, dizendo que há novidades e o obriga a fazer um pull, seguido de um merge. Aí, o outro fica com uma história assim:

2015-05-09 06:22 Hani Camille Yehia M─┐ Merge branch 'master' of www.cefala.org:blog
2015-05-09 11:16 Rafael Laboissiere  o Use the correct name for the git-multimail command
2015-05-09 06:20 Hani Camille Yehia o  Include command to define 'ci' as an alias to 'commit' in article 'o-git-me-manda-noticias'
2015-05-09 06:10 Hani Camille Yehia o─┘ Add Hani's email address to the push notification mailing list

(Abrindo parêntese rapidinho, o que está mostrado acima é uma cópia das linhas do Tig. Trata-se de uma interface totalmente textual para visualizar a história do Git, sem aqueles frufrus todos das interfaces tipo Click-O-Rama. Fecha parêntese.)

Bom, a história ficou feia de com força, por causa daquele commit "Merge branch etc.". Felizmente, o Git, como nos bons tempos do Stalinismo e do KGB, é capaz de reescrever a história e evitar que você passe constrangimento ao fazer o git push. Normalmente, o fluxo de trabalho com Git deve ser o seguinte:

$ git pull
$ editor some-file
$ git pull
$ git add some-file
$ git commit -m "Changed some file"
$ git push
Great, thanks for your contribution!

Note que eu coloquei duas vezes git pull acima. O primeiro, você faz antes de introduzir as suas modificações. Entretanto, estas modificações podem durar horas ou dias. É por isto que recomendo o segundo git pull. De qualquer maneira, a sequência pull/add/commit/push deve ser feita rapidamente.

Agora, problemas acontecem quando você deixa de fazer o git pull na hora certa. Aí, pode dar nisto:

$ editor some-file
$ git add some-file
$ git commit -m "Changed some file"
$ git push
You, moron, do a git pull first!
$ git pull
Ha!  I will force you to do an ugly merge!
$ git push

Quando isto ocorrer, chame o super git rebase e ele virá ao seu socorro. Santa rebaseada, Batman! Logo após o git pull, lance os comandos seguintes e a história voltará a ser linear, como se nada tivesse acontecido, não é mesmo, Vladimir?

$ git rebase remotes/origin/master master
$ git push

Uma outra maneira de evitar todo e qualquer problema é o uso sistemático da opção --rebase do command git pull.

P.S.: Por falar em reescrever a história, a Rússia festejou hoje o armistício da Segunda Guerra Mundial, com toda pompa militar de uma ex-URSS. Eles gostam de ser diferentes do resto do mundo, que festejou o armistício ontem, no dia 8 de maio. Muito se falou por aqui na Europa, nestes últimos dias, da tomada do Reichstag em Berlim pelo Exército Vermelho. Aí eu me lembrei daquela famosa foto do hasteamento da bandeira soviética. Notem que a foto, que foi toda preparada pela propaganda soviética, teve que ser retocada antes da publicação, pois aparecia nela um soldado com relógios nos dois pulsos, prova da pilhagem constrangedora de guerra. No bom estilo Git (o retoque, é claro, não a pilhagem!).

social