Você está na página 1de 45

Magia Git

Ben Lynn

Magia Git
Ben Lynn Tradutor: Leonardo Siqueira Rodrigues {leonardo.siqueira.rodrigues@gmail.com}

Informaes sobre a traduo

Fonte utilizadas Anonymous Pro1 ABCDEFGHIJKLMOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 012456789

APHont2

ABCDEFGHIJKLMOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 012456789 3 Diavlo Black ABCDEFGHIJKLMOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 012456789

Padres que tentei usar no texto: Termos estrangeiros no singular. Assim, quando necessrio mudei as frases para que o termo no singular encaixasse melhor; Manter o nome Git com o "g" maisculo; Seguir a conveno abaixo na formatao do texto: Itlico para palavras estrangeiras, nome de comandos quando substantivados. Exemplo: "... no primeiro commit...", "... um backup..."; Negrito para comandos, nome de diretrios. Exemplo: "... ajuda do git help re-parse...".

Toda ajuda para corrigir e/ou melhorar o documento bem-vinda.

1 http://www.ms-studio.com/FontSales/anonymouspro.html 2 http://www.aph.org/products/aphont.html 3 http://www.exljbris.nl

NDICE
Prefcio..................................................................7 Agradecimentos!......................................................7 Licena...................................................................7 Links......................................................................8

Introduo..........................................................9

Trabalhar Divertido...............................................9 Controle de Verses.................................................9 Controle distribudo................................................10 Conflitos de mesclagem (Merge)...............................11


Uma superstio...................................................................11

Truques bsicos..............................................12

Salvando estados...................................................12 Desfazer/Refazer avanado......................................13 Download de arquivos.............................................14 ltima Verso........................................................14 Publicao instantnea............................................14 O que eu fiz?.........................................................15
Revertendo..........................................................................14 Adicionar, Remover, Renomear................................................12

Um pouco de clonagem.................................16

Sincronizando Computadores...................................16 Controle clssico de cdigo......................................16 Fazendo um Fork do Projeto.....................................17 Backup Supremos..................................................17 Multitarefa na velocidade da luz...............................18 Controle de Verses de Guerrilha..............................18 A tecla chefe.......................................................20 Trabalho porco.......................................................21 Correes rpidas..................................................22

Bruxaria com branch.....................................20

Fluxo ininterrupto..................................................22 Reorganizando uma improvisao.............................23 Gerenciando o Branch.............................................23 Branch Temporrios...............................................24 Trabalhe como quiser..............................................24

Lies de historia...........................................26

Estou correto.........................................................26 e tem mais.........................................................26 Alteraes locais por ltimo.....................................27 Reescrevendo o histrico.........................................27 Fazendo histria....................................................28 Onde tudo comeou a dar errado?............................29 Quem Fez Tudo Dar Errado?....................................30 Experincia pessoal................................................30 Disponibilizao de Cdigo.......................................32 Gerao do Registro das Modificaes........................32 Git por SSH, HTTP.................................................32 Git Acima de Tudo..................................................33 Commit do que Mudou............................................33 Meu Commit To Grande!.....................................34 No perca a CABEA (HEAD)...................................35 Explorando o HEAD................................................35 Baseando se no Git.................................................36 Dubls Duros na Queda...........................................37 Invisibilidade.........................................................39 Integridade...........................................................39 Inteligncia...........................................................40 Indexando............................................................41 Repositrios Crus...................................................41 Origem do Git.......................................................41

Gro-Mestre Git.............................................32

Segredos Revelados.......................................39

Atalhos do Git.................................................42

Microsoft Windows.................................................42 Arquivos Independentes..........................................42 Quem Est Editando O Que?....................................42 Arquivo do Histrico...............................................43 Clone Inicial..........................................................43 Projetos Volteis....................................................43 Contador Global.....................................................44 Subdiretrios Vazios...............................................44 Commit Inicial.......................................................45

Magia Git

Prefcio
Git4 um canivete suo do controle de verses. Uma ferramente polivalente realmente verstil cuja extraordinria flexibilidade torna-o complicado de aprender, sobre tudo sozinho. Coloquei nestas paginas o pouco que aprendi, pois inicialmente tive dificuldade em compreender o manual do usurio do Git5. Como Arthur C. Clarke6 bem comentou: Qualquer tecnologia suficientemente avanada considerada magica. Esta uma tima forma de abordar o Git: novatos podem ignorar seu funcionamento interno e v-lo como algo divertido que pode agradar aos amigos e enfurecer os inimigos com suas horrendas habilidades. Ao invs de entrar em detalhes, forneceremos apenas instrues para casos especficos. Aps o uso repetido, voc gradualmente entender como cada truque, e como adaptar as receitas s suas necessidades. Outras Edies Traduo Chinesa7: por JunJie, Meng e JiangWei. Pagina nica8: HTML, sem CSS. Arquivo PDF9: pronto para imprimir.

Agradecimentos!
Agradecimentos a Dustin Sallings, Alberto Bertogli, James Cameron, Douglas Livingstone, Michael Budde, Richard Albury, Tarmigan e Derek Mahar pelas sugestes e melhorias. [Se esqueci de voc, por favor avise, as vezes esqueo de atualizar esta seco.]

Licena
Este guia regido pelos termos da the GNU General Public License version 310. Naturalmente, os fontes esto num repositrio Git, e so obtido digitando:
$ git clone git://repo.or.cz/gitmagic.git # Cria a pasta "gitmagic".

Veja a seguir outros locais.


4 http://git-scm.com/ 5 http://www.kernel.org/pub/software/scm/git/docs/user-manual.html 6 http://pt.wikipedia.org/wiki/Arthur_C._Clarke 7 http://docs.google.com/View?id=dfwthj68_675gz3bw8kj 8 http://www-cs-students.stanford.edu/~blynn/gitmagic/book.html 9 http://www-cs-students.stanford.edu/~blynn/gitmagic/book.pdf 10 http://www.gnu.org/licenses/gpl-3.0.html

Links
Uma vez listei algumas referncias, porm consome muito tempo mante-las. Alm disso, qualquer um pode usar um site de busca para encontrar tutoriais, guias e comparaes do Git com Subversion11, Mercurial12, ou outro sistema de controle de verses. Repositrios Git grtis http://repo.or.cz/ hospeda projetos livres, inclusive este guia. http://gitorious.org/ outro site de hospedagem Git destinado a projetos de cdigo aberto. http://github.com/ hospeda projetos de cdigo aberto de graa, inclusive este guia, e projetos privados tambm.

11 http://subversion.tigris.org/ 12 http://www.selenic.com/mercurial/

Magia Git

Introduo
Usarei uma analogia para falar sobre controle de verses. Veja na Wikipdia o verbete sistema de controle de verses13 para uma melhor explicao .

Trabalhar Divertido
Me divirto com jogos para computador quase minha vida toda. Em contrapartida, s comecei a usar sistemas de controle de verses quando adulto. Suspeito que no fui o nico, e comparar os dois pode tornar estes conceitos mais fceis de explicar e entender. Pense na edio de seu cdigo, documento, ou qualquer outra coisa, como jogar um jogo. Uma vez que tenha feito muitos progressos, e gostaria de de salvalos. Pra isso, voc clica em Salvar no seu editor preferido. Porm isto vai sobrescrever a verso anterior. como nos antigos jogos onde voc s tinha uma espao para salvar: voc pode salvar, mas nunca mais poder voltar a um estado salvo anteriormente. O que um pena, pois o estado anterior era uma parte muito divertida do jogo e voc gostaria de poder revisita-lo outra hora. Ou pior, o ultimo estado salvo um dificlimo e voc ter que recomear.

Controle de Verses
Ao editar, voc pode Salvar como ... num arquivo diferente, ou copiar o arquivo antes de sobrescreve-lo se voc quiser manter as verses anteriores. Pode comprimi-los para economizar espao. Isto uma forma rudimentar e muito trabalhosa de controle de verses. Jogos de computador aperfeioaram este mtodo, muitos deles acrescentam automaticamente a data e a hora aos estados salvos. Vamos dificultar um pouco. Digamos que so um monte de arquivos juntos, como os fontes do seu projeto, ou arquivos para um website. Agora se quiser manter suas verses anteriores, ter que arquivar todo um diretrio ou vrios. Manter muitas verses na mo inconveniente e rapidamente se tornar caro. Em alguns jogos de computador, um estado salvo consiste de um diretrio cheio de arquivos. Estes jogos escondem estes detalhes do jogador e lhe apresentam uma interface conveniente para gerenciar as diferentes verses neste diretrio.
13 http://pt.wikipedia.org/wiki/Sistema_de_controle_de_verso

10

Introduo

Sistemas de controle de verses no so diferentes. Todos tem uma boa interface para gerenciar seu diretrio de verses. Voc pode salvar o diretrio sempre que desejar, e pode rever qualquer um dos estado salvos quando quiser. Ao contrrio da maioria dos jogos de computador, eles so geralmente mais espertos na economia de espao. Normalmente, apenas uns poucos arquivos mudam de verso para verso, e com poucas diferenas. Armazenar as diferenas, ao invs de todos os arquivos, economiza espao.

Controle distribudo
Agora imagine um jogo de computador muito difcil. To difcil de terminar que vrios jogadores experientes pelo mundo decidem formar uma equipe e compartilhar seus estados salvos do jogo para tentar vence-lo. Speedruns so exemplos reais: jogadores especializados em diferentes nveis do mesmo jogo colaboram na produo de resultados incrveis. Como voc configura um sistema para que todos possam obter facilmente o que os outros salvarem? E salvar novos estados? Nos velhos tempos, todos os projetos utilizava controle de verses centralizado. Um servidor em algum lugar mantm os jogos salvos. Ningum tem todos. Cada jogador mantm, em sua maioria, apenas alguns jogos salvos em suas maquinas. Quando algum jogador quiser avanar no jogo, ele pega o ultimo jogo salvo do servidor, joga um pouco, salva e manda de volta para o servidor para que os outros possam usar. E se um jogador quiser pegar um antigo jogo salvo por algum motivo? Talvez o atual jogo salvo esteja em um nvel impossvel de jogar devido algum ter esquecido um objeto trs nveis atrs, e preciso encontrar o ultimo jogo salvo que est em um nvel que pode ser completado com sucesso. Ou talvez queira comparar dois jogos salvo para saber o quanto um jogador avanou. Podem existir vrios motivos para ver uma verso antiga, mas o modus operandi o mesmo. Tm que solicitar ao servidor centralizado a antiga verso. E quanto mais jogos salvos forem necessrios, maior o trafego de informao. A nova gerao de sistemas de controle de verses, dentre eles o Git, conhecida como sistemas distribudos, e pode ser pensada como uma generalizao dos sistemas centralizados. Quando os jogadores pegam do servidor, eles recebem todos os jogos salvos, e no apenas o mais recente. como se estivessem espelhando o servidor. A primeira operao de clonagem pode ser bem demorada, especialmente se h um longo histrico, mas compensada no longo prazo. Um beneficio imediato que, se por qualquer raso desejar uma antiga verso, a trafego de informao com o servidor desnecessrio.

Magia Git

11

Uma superstio
Um equvoco popular que sistemas distribudos esto mal adaptados projetos que exijam um repositrio central oficial. Nada poderia estar mais longe da verdade. Fotografar algum roubara sua alma. Igualmente, clonar o repositrio master no diminui sua importncia. Uma boa comparao inicial : qualquer coisa que um sistema centralizado de controle de verses faz, um sistema distribudo de controle de verses bem concebido pode fazer melhor. Recursos de rede simplesmente mais oneroso que recursos locais. Embora vejamos mais adiante que existem inconvenientes numa abordagem distribuda, menos provvel que faa comparaes errneas com esta regra de ouro. Um pequeno projeto pode precisar de apenas uma frao dos recursos oferecidos pelo sistema. Mas, voc usa algarismos romanos quando calcula com nmeros pequenos? E mais, seu projeto pode crescer alm da suas expectativas. Usando Git, desde o inicio como ter um canivete suo, embora o use na maioria das vezes para abrir garrafas. No dia que necessitar, desesperadamente, de uma chave de fenda voc agradecer por ter mais do que um abridor de garrafas.

Conflitos de mesclagem (Merge)


Neste tpico, nossa analogia com jogos de computador tornasse ruim. Em disso, vamos considerar novamente a edio de um documento. Suponha que Alice insira uma linha no inicio do arquivo, e Bob uma no final. Ambos enviam suas alteraes. A maioria dos sistemas ir de maneira automtica e reativa deduzir o plano de ao: aceitando e mesclando as mudanas, assim as alteraes de Alice e Bob sero aplicadas. Agora suponha que ambos, Alice e Bob, faam alteraes distintas na mesma linha. Tornando impossvel resolver o conflito sem interveno humana. O segundo, entre Alice e Bob, que enviar suas alteraes ser informado do conflito, e escolher se aplica sua alterao sobre a do outro, ou revisa a linha para manter ambas as alteraes. Situaes muito mais complexas podem surgir. Sistemas de controle de verses so capazes de resolver os casos mais simples, e deixar os casos mais difceis para nos resolvermos. Normalmente seu comportamento configurvel.

12

Truques Bsicos

Truques Bsicos
Ao invs de se aprofundar no mar de comandos do Git, use estes exemplos elementares para dar os primeiros passos. Apesar de suas simplicidades, cada um deles so muito teis. Na verdade, no meu primeiro ms com o Git, nunca precisei ir alm das informaes deste captulo.

Salvando estados
Pensando em tentar algo mais arriscado? Antes de faz-lo, tire um fotografia de todos os arquivos do diretrio atual com:
$ git init $ git add . $ git commit -m "Meu primeiro backup"

A sequncia de comandos acima devem ser memorizados, ou colocados em um script, pois sero usados com muita frequncia. Assim se algo der errado, voc s precisar executar:
$ git reset --hard

para voltar para o estado anterior. Para salvar o estado novamente, faa:
$ git commit -a -m "Outro backup"

Adicionar, Remover, Renomear


Os comandos acima s iro verificar alteraes os arquivos que estavam presentes quando voc executou seu primeiro git add. Se voc adicionar novos arquivos ou diretrios tira que informar ao Git, com:
$ git add NOVOSARQUIVOS...

Do mesmo modo, se voc quiser que o Git na verifique certos arquivos, talvez por t-los apagados, faa:
$ git rm ANTIGOSARQUIVOS...

Renomear um arquivo o mesmo que remover nome antigo e adicionar um novo nome. H tambm o atalho git mv que tem a mesma sintaxe do comando mv. Por exemplo:
$ git mv ANTIGOARQUIVO NOVOARQUIVO

Magia Git

13

Desfazer/Refazer avanado
s vezes, voc s quer voltar e esquecer todas as mudanas realizadas a partir de um certo ponto, pois esto todos erradas. Ento:
$ git log

mostrar uma lista dos ltimos commit e seus hash SHA1. Em seguida, digite:
$ git reset --hard SHA1_HASH

para restaurar ao estado de um dado commit e apagar os registros de todos os novos commit a partir deste ponto permanentemente. Outras vezes voc quer voltar, brevemente, para um estado. Neste caso, digite:
$ git checkout SHA1_HASH

Isto levar voc de volta no tempo, preservando os novos commit. Entretanto, como nas viagens no tempo do filmes de fico, se voc editar e fizer um commit, voc estar nume realidade alternativa, pois suas aes so diferentes das realizadas da primeira vez. Esta realidade alternativa chamada de branch, ns falaremos mais sobre isso depois. Por hora, apenas lembre-se que:
$ git checkout master

lhe levar de volta para o presente. Assim faa o Git parar de reclamar, sempre faa commit ou reset suas mudanas antes de executar um checkout. Voltemos para a analogia dos jogos de computador : git reset --hard: carrega um antigo salvamento e apagar todos os salvamento mais novos do que este que foi carregado. git checkout: carrega um antigo salvamento, mas se jogar a partir dele, os prximos salvamento realizados se desvincularo dos salvamentos j realizados aps o que foi carregado. Qualquer salvamento que voc fizer ser colocado em um branch separado representado a realidade alternativa em que entrou. Lidaremos com isso mais a frente. Voc pode escolher restaurar apenas alguns arquivos ou diretrios acrescentando-os ao final do comando. No gosta de copiar e colar hash? Ento use:
$ git checkout :/"Meu primeiro b"

14

Truques Bsicos

para ir ao commit que comea a frase informada. Voc tambm pode solicitar pelo estado salvo a 5 commit atrs:
$ git checkout master~5

Revertendo
Como num tribunal, eventos podem ser retirados dos registros. Igualmente, voc pode especificar qual commit desfazer.
$ git commit -a $ git revert SHA1_HASH

ir desfazer apenas o commit do hash informado. Executando git log revelar que a regresso gravada como um novo commit.

Download de arquivos
Obtenha a cpia dum projeto gerenciado com GIT digitando:
$ git clone git://servidor/caminho/dos/arquivos

Por exemplo, para obter todos os arquivos usados para criar este site:
$ git clone git://git.or.cz/gitmagic.git

A seguir, teremos muito o que dizer sobre o comando clone.

ltima Verso
Se voc j obteve a copia de um projeto usando git clone, pode agora atualizar para a ltima verso com:
$ git pull

Publicao instantnea
Suponha que voc tenha escrito um script e gostaria de compartilha-lo. Voc poderia simplesmente dizer para pegarem do seu computador, mas se o fizerem enquanto voc esta melhorando o script ou experimentado algumas mudanas, eles podem ter problemas. Obviamente, por isso que existem ciclos de liberao. Desenvolvedores podem trabalhar num projeto com frequncia, mas s disponibilizam o cdigo quando sentem que o mesmo esta apresentvel. Para fazer isso com Git, no diretrio onde est seu script, execute:

Magia Git

15

$ git init $ git add . $ git commit -m "Primeira liberao"

Ento avise aos outros para executarem:


$ git clone seu.computador:/caminho/do/script

para obter seu script. Assume-se que eles tm acesso ssh. Se no, execute git daemon e avise-os para executar:
$ git clone git://seu.computador/caminho/do/script

A partir de agora, toda vez que seu script estiver pronto para liberar, execute:
$ git commit -a -m "Nova liberao"

e seu usurios podem atualizar suas verses, indo para o diretrio que contm seu script, e executando:
$ git pull

Seu usurios nunca ficaro com uma verso do seu script que voc no queira. Obviamente este truque serve para tudo, no apenas script.

O que eu fiz?
Saiba quais as mudanas que voc fez desde o ltima commit com:
$ git diff

Ou desde ontem:
$ git diff "@{yesterday}"

Ou entre uma verso particular e duas verses atrs:


$ git diff SHA1_HASH "master~2"

Tente tambm:
$ git whatchanged --since="2 weeks ago"

As vezes navego pelo histrico com o qgit14, em razo de sua interface mais fotognica, ou com o tig15, uma interface em modo texto tima para conexes lentas. Alternativamente, instale um servidor web, execute git instaweb e use um navegador.

14 http://sourceforge.net/projects/qgit 15 http://jonas.nitro.dk/tig/

16

Um Pouco De Clonagem

Um Pouco De Clonagem
Em sistemas de controle de verses mais antigos, checkout a operao padro para se obter arquivos. Obtendo assim os arquivos do ponto de salvamento informado. No Git e em outros sistemas distribudos de controle de verses, clonagem a operao padro. Para obter os arquivos clonasse o repositrio inteiro. Em outras palavras, voc praticamente faz um espelhamento do servidor central. Tudo o que se pode fazer no repositrio principal, voc pode fazer no seu repositrio local.

Sincronizando Computadores
Esta foi a razo pela qual usei o Git pela primeira vez. Eu posso aguentar fazer tarball16 ou usar o rsync para backup e sincronizaes bsicas. Mas as vezes edito no meu laptop, outras no meu desktop, e os dois podem no ter conversado entre si nesse perodo. Inicialize um repositrio Git e commit seus arquivos em uma das maquinas. Ento na outra:
$ git clone outro.computador:/caminho/dos/arquivos

para criar uma segunda copia dos seus arquivos e do repositrio Git. A partir de agora, use:
$ git commit -a $ git pull outro.computador:/caminho/dos/arquivos

o que deixar os arquivos da maquina em que voc est trabalhando, no mesmo estado que esto no outro computador. Se voc recentemente fez alguma alterao conflitante no mesmo arquivo, o Git lhe informar e voc poder fazer um novo commit e ento escolher o que fazer para resolv-lo.

Controle clssico de cdigo


Inicialize um repositrio Git para seus arquivos:
$ git init $ git add . $ git commit -m "Commit inicial"

No servidor principal, inicialize um repositrio Git em branco com o mesmo


16 http://pt.wikipedia.org/wiki/TAR

Magia Git

17

nome, e inicie o daemon Git se necessrio:


$ GIT_DIR=proj.git git init $ git daemon --detach # Ele pode j estar sendo executado

Algumas hospedagens publicas, tais como o repo.or.cz, tero mtodos diferentes para configurar o repositrio inicial em branco, como atravs do preenchimento de um formulrio no site deles. Mande seu projeto para o servidor principal com:
$ git push git://servidor.principal/caminho/do/proj.git HEAD

Estamos prontos. Para verificar os fontes, um desenvolvedor pode digitar:


$ git clone git://servidor.principal/caminho/do/proj.git

Aps realizar as alteraes, o cdigo enviado para o servidor com:


$ git commit -a $ git push

Se o servidor principal tiver sido atualizado enquanto realizava as alteraes, ser necessrio obter a ltima verso antes de enviar as alteraes. Para sincronizar para a ltima verso:
$ git commit -a $ git pull

Fazendo um Fork17 do Projeto


Chateado com a rumo que o projeto esta tomando? Acha que pode fazer o trabalho melhor? Ento no seu servidor:
$ git clone git://servidor.principal/caminho/dos/arquivos

Em seguida avise a todos sobre seu fork do projeto no seu servidor. Qualquer hora depois, voc pode mesclar (merge) suas mudanas do projeto original no mesmo com:
$ git pull

Backup Supremos
Gostaria de numerosos arquivos geograficamente dispersos, redundantes e anti-falsificaes? Se seu projeto tem muitos desenvolvedores, no faa nada! Cada clonagem do seu cdigo um backup efetivo. E no apenas uma cpia do
17 http://pt.wikipedia.org/wiki/Fork

18

Um Pouco De Clonagem

estado atual, e sim o histrico completo do seu projeto. Graas ao hash criptogrfico, se cada clonagem for corrompida, ele ser identificado assim que tentar se comunicar com os outros. Se seu projeto no to popular, encontre quantos servidores puder para hospedar seus clones. Um paranoico verdadeiro sempre anotar os ltimos 20 byte do hash SHA1 do cabealho (HEAD) em algum lugar seguro. Tem que ser seguro, e no privado. Por exemplo, publica-lo em um jornal funciona bem, pois muito difcil para um atacante alterar todas as cpias de um jornal.

Multitarefa na velocidade da luz


Digamos que voc queira trabalhar em diversas funes em paralelo. Ento faa um commit do seu projeto executando:
$ git clone . /algum/novo/diretrio

Git explora, at onde for seguramente possvel, hard links e compartilhamento de arquivos para criar este clone, assim isto deve ficar pronto em um instante, e voc pode agora trabalhar e duas funes independentes simultaneamente. Por exemplo, voc pode editar um clone enquanto o outro compilado. A qualquer momento, voc pode fazer um commit e pegar as alteraes de outro clone
$ git pull /o/outro/clone

Controle de Verses de Guerrilha


Voc est trabalhando em um projeto que utiliza outro sistema de controle de verses, sofrer a perda do Git? Inicialize um repositrio Git no seu diretrio de trabalho:
$ git init $ git add . $ git commit -m "Commit inicial"

clone-o, na velocidade da luz:


$ git clone . /algum/novo/diretrio

Agora vai para o novo diretrio e trabalhe nele, no no anterior, usando Git para felicidade geral da nao. De vez em quando voc desejar sincronizar com os outros, neste caso, v para o diretrio original, sincronize usando o outro sistema de controle de verses, e ento digite:

Magia Git

19

$ git add . $ git commit -m "Sincronizando com os outros"

Depois v para o novo diretrio e execute:


$ git commit -a -m "Descrio das minhas alteraes" $ git pull

O procedimento para enviar suas alteraes para os outros depende do outro sistema de controle de verses. O novo diretrio contm os arquivos com as suas alteraes. Execute qualquer comando do outro sistema de controle de verses necessrio para envia-las para o repositrio central. O comando git svn automatiza tudo isso para repositrios Subversion, e tambm pode ser utilizado para exportar um repositrio Git para um repositrio Subversion18.

18 http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html

20

Bruxaria Com Branch

Bruxaria Com Branch


Ramificaes (Branch) e mesclagens (merge) instantneos so as caractersticas mas fantsticas do Git. Problema: Fatores externos inevitavelmente exigem mudanas de contexto. Um erro grave que se manifesta sem aviso, em uma verso j liberada. O prazo final diminudo. Um desenvolvedor que o ajuda, em uma funo chave do seu projeto, precisa sair. Em todos os casos, voc abruptamente deixar de lado o que esta fazendo e focar em uma tarefa completamente diferente. Interromper sua linha de pensamento provavelmente prejudicar sua produtividade, e quanto mais trabalhoso trocar de contexto, maior a perda. Com um controle de verses centralizado precisamos pegar uma nova cpia do servidor central. Sistemas distribudos fazem melhor, j que podemos clonar o que quisermos localmente. Mais clonar ainda implica copiar todo o diretrio de trabalho, bem como todo o histrico at o ponto determinado. Mesmo o custo reduzido no espao usado pelos arquivos que o Git tem com o compartilhamento destes arquivos, os arquivos do projeto em si so recriados na integra no novo diretrio. Soluo: O Git tem a melhor ferramenta para estas situaes que muito mais rpida e mais eficiente no uso de espao do que a clonagem: git branch. Com esta palavra mgica, os arquivos em seu diretrio de repente mudam de forma, de uma verso para outra. Esta transformao pode fazer mais do que apenas avanar ou retroceder no histrico. Seus arquivos podem mudar a partir da ltima liberao para a verso experimental, para a verso atualmente em desenvolvimento, ou para a verso dos seus amigos, etc.

A tecla chefe
Sempre jogue um desses jogos que ao apertar de um boto (a tecla chefe), a tela instantaneamente mudar para uma planilha ou algo mais srio. Assim se o chefe passar pelo seu escritrio enquanto voc estiver jogando, poder rapidamente esconder o jogo. Em algum diretrio:
$ $ $ $ echo "Sou mais esperto que meu chefe" > meuarquivo.txt git init git add . git commit -m "Commit inicial"

Magia Git

21

Criamos um repositrio Git que rastrear um arquivo texto contendo uma certa mensagem. Agora digite:
$ git checkout -b chefe # nada parece ter mudado aps isto $ echo "Meu chefe mais esperto que eu" > meuarquivo.txt $ git commit -a -m "Outro commit"

ficou parecendo que ns sobrescrevemos nosso arquivo e fizemos um commit. Mas isto um iluso. Digite:
$ git checkout master # troca para a verso original do arquivo

e tcham tcham tcham! O arquivo texto foi restaurado. E se o chefe decidir rondar este diretrio. Digite:
$ git checkout chefe # troca para verso adaptada para agradar o chefe

Voc pode trocar entre as duas verses do arquivo quantas vezes quiser, e fazer commit independentes para cada uma.

Trabalho porco
Digamos que voc est trabalhando em alguma funo, e por alguma razo, precisa voltar para uma antiga verso e temporariamente colocar algumas declaraes de controle para ver como algo funciona. Ento:
$ git commit -a $ git checkout SHA1_HASH

Agora voc pode adicionar temporariamente cdigo feio em todo canto. Pode at fazer commit destas mudanas. Quando estiver tudo pronto,
$ git checkout master

para voltar para o trabalho original. Observe que qualquer mudana sem commit so temporrias. E se voc desejasse salvar as mudanas temporrias depois de tudo? Fcil:
$ git checkout -b sujeira

e faa commit antes de voltar ao branch master. Sempre que quiser voltar sujeira, simplesmente digite:
$ git checkout sujeira

Ns j falamos deste comando num captulo anterior, quando discutimos carregamento de antigos estados salvos. Finalmente podemos contar toda a histria: os arquivos mudam para o estado requisitado, porm samos do branch master. Cada commit realizado a partir deste ponto nos seus arquivos o levaro em outra

22 direo, que nomearemos mais a diante.

Bruxaria Com Branch

Em outra palavras, depois de fazer checkout em um estado antigo, o Git automaticamente o colocar em um novo branch no identificado, que pode ser identificado e salvo com git checkout -b.

Correes rpidas
Voc esta fazendo algo quando mandam largar o que quer que seja e corrigir um erro recm descoberto:
$ git commit -a $ git checkout -b correes SHA1_HASH

Ento assim que tiver corrigido o erro:


$ git commit -a -m "Erro corrigido" $ git push # envia para o repositrio principal $ git checkout master

e volte a trabalhar no que estava fazendo anteriormente.

Fluxo ininterrupto
Alguns projetos requerem que seu cdigo seja revisado antes que o envie. Para tornar a vida fcil daqueles que forem revisar seu cdigo, se voc tem um a grande mudana para fazer, voc pode quebra em dois ou mais partes, e ter cada parte revisada separadamente. E se a segunda parte no puder ser escrita at que a primeira seja aprovada e revisada? Em muitos sistemas de controle de verses, voc teria que mandar a primeira parte para os revisores, e aguardar at que seja aprovada para ento comear a segunda parte. Atualmente isso no verdade, mas nestes sistemas de edio da segunda parte antes da primeira ser aprovada envolve muito sofrimento e privaes. No Git, os branch e merge so indolores (termo tcnico para rpido e local). Ento aps fazer o commit da primeira parte e enviado para reviso:
$ git checkout -b parte2

Em seguida, codifique a segunda parte da grande mudana sem esperar que a primeira parte tenha sido aceita. Quando a primeira parte for aprovada e enviada,
$ git checkout master $ git merge parte2 $ git branch -d parte2 # no precisar mais deste branch

Magia Git

23

e a segunda parte das mudanas est pronta para ser revisada. Mais espere! E se no for to simples? Digamos que voc cometeu em erro na primeira parte, que voc tem que corrigir antes de envia-la. Sem problema! Primeiro, volte para branch master com:
$ git checkout master

Corrija o problema da primeira parte das mudanas e aguarde a aprovao. Se no simplesmente repita este passo. Voc provavelmente desejar fazer um merge da verso corrigida da primeira parte com a segunda, logo:
$ git checkout part2e $ git merge master

Agora como anteriormente. Logo que a primeira parte for aprovada e enviada:
$ git checkout master $ git merge parte2 $ git branch -d parte2

e, novamente, a segunda parte est pronta para a reviso. fcil estender este truque para qualquer nmero de partes.

Reorganizando uma improvisao


Talvez voc goste de trabalhar com todos os aspectos de um projeto num mesmo branch. E gostaria de trabalhar e que os outros s vejam seus commit, apenas quando eles estiverem organizados. Inicie um par de branch:
$ git checkout -b organizado $ git checkout -b desorganizado

A seguir, trabalhe em alguma coisa: corrigindo erros, adicionando funes, adicionando cdigo temporrio, e assim por diante, faa commit muitas vezes ao longo do caminho. Ento:
$ git checkout organizado $ git cherry-pick SHA1_HASH

aplique um dado commit ao branch "organizado". Com os cherry-picks apropriados voc pode construir um branch que contm apenas cdigo permanente, e tem commit relacionados agrupados juntos.

Gerenciando o Branch
Digite:
$ git branch

24

Bruxaria Com Branch

para listar todos os branch. H sempre um branch chamado "master", e voc comea por aqui, por default. Alguns defendem que o branch master deve ser intocvel e criar novos branch para suas prprias mudanas. As opes -d e -m permitem a voc deletar ou mover (renomear) um branch. Veja git help branch.

Branch Temporrios
Depois de um tempo voc perceber que est criando branch de curta durao, frequentemente e por motivos parecidos: cada novo branch serve apenas para guardar o estado atual, assim voc pode rapidamente voltar para estados antigos para corrigir um erro ou algo assim. anlogo a mudar o canal da TV temporariamente para ver o que esta passando nos outros canais. Mas, ao invs de apertar dois botes, voc esta criando, checando e apagando branch temporrios e seus commit. Felizmente, o Git tem um atalho que to conveniente como um controle remoto de TV:
$ git stash

Isto salva o estado atual num local temporrio (um stash) e restaura o estado anterior. Seu diretrio de trabalho parece ter voltado ao estado anteriormente salvo, e voc pode corrigir erros, puxar as mudanas mais novas, e assim por diante. Quando quiser retornar ao estado anterior ao uso do stash, digite:
$ git stash apply # Pode ser preciso resolver alguns conflitos.

Voc pode ter mltiplos stash, e manipula-los de vrias formas. Veja git help stash. Como deve ter adivinhado, o Git usa branch por traz dos panos para fazer este truque.

Trabalhe como quiser


Aplicaes como Mozilla Firefox19 permitem que se abra mltiplas abas e mltiplas janelas. Alternando entre as abas temos diferentes contedos na mesma janela. Branch no Git so como abas para seu diretrio de trabalho. Seguindo na analogia, a clonagem no Git como abrir uma nova janela. Ser capaz de fazer ambos, melhora a experincia do usurio. Num nvel mais alto: vrios gerenciadores de janelas no linux20 permitem a existncia de vrias reas de trabalho: e instantaneamente alternar entre elas. O que similar ao branch no Git, enquanto a clonagem seria como anexar outro monitor para ganhar mais uma rea de trabalho.
19 http://www.mozilla.com/ 20 http://www.linux.org

Magia Git

25

Outro exemplo o utilitrio screen21. Esta preciosidade lhe permite criar, destruir e alternar entre mltiplas sesses de terminais no mesmo terminal. Ao invs de abrir novos terminais (clone), voc pode use o mesmo se usar o screen (branch). Na realidade, voc pode fazer muito mais com o screen mas isso assunto para outro texto. Clonagem, branch e merge so rpidos e locais no Git, encorajando-o a usar a combinao que mais lhe convir. Git deixa voc trabalhar exatamente como quiser.

21 http://www.gnu.org/software/screen/

26

Lies De Historia

Lies De Historia
Uma consequncia da natureza distribuda do Git que o histrico pode ser editado facilmente. Mas se voc adulterar o passado, tenha cuidado: apenas rescreva a parte do histrico que s voc possui. Assim como as naes sempre argumentam sobre quem comete atrocidades, se algum tiver um clone cuja verso do histrico seja diferente do seu, voc pode ter problemas para conciliar suas rvores quando interagirem. Claro, se voc controlar todas as outras rvores tambm, ento no h problema, uma vez que pode sobrepor-las. Alguns desenvolvedores gostam de um histrico imutvel, com falhas ou no. Outros, que suas rvores estejam apresentveis antes de libera-las ao pblico. O Git contempl ambos pontos de vista. Tal como clonagem, branch e merge, rescrever o histrico simplesmente outro poder que o Git lhe concede. Cabe a voc a us-lo sabiamente.

Estou correto
Acabou de fazer um commit, mas queria ter escrito uma mensagem diferente? Ento execute:
$ git commit --amend

para mudar a ultima mensagem. Percebeu que esqueceu de adicionar um arquivo? Execute git add para adiciona-lo, e ento execute o comando acima. Quer incluir mais algumas modificaes no ultimo commit? Faa-as e ento execute:
$ git commit --amend -a

e tem mais
Suponha que o problema anterior dez vezes pior. Aps uma longa sesso onde fez um monte de commit. E voc no est muito feliz com a organizao deles, e algumas das mensagens dos commit poderiam ser reformuladas. Ento execute:
$ git rebase -i HEAD~10

e os ltimos 10 commit aparecero em seu $EDITOR favorito. Trecho de exemplo:

Magia Git

27

pick 5c6eb73 Adicionado link para repo.or.cz pick a311a64 Reorganizadas as analogias em "Trabalhe como quiser" pick 100834f Adicionado origem (push target) ao Makefile

Ento: Remova os commit deletando linhas; Reorganize os commit reorganizando linhas; Substitua pick por edit para modificar a mensagem do commit; Substitua pick por squash para unir (merge) um commit com o anterior. Se marcar um commit para edio, execute:
$ git commit --amend

Caso contrrio, execute:


$ git rebase --continue

Portanto, faa commit cedo e com freqncia: e arrume tudo facilmente mais tarde com um rebase.

Alteraes locais por ltimo


Voc esta trabalhando em um projeto ativo. Faz alguns commit locais ao longo do tempo, e sincroniza com a rvore oficial com merge. Este ciclo se repete algumas vezes at estar tudo pronto para ser enviado rvore central. Mas agora o histrico no seu clone local esta uma confuso com o emaranhado de modificaes locais e oficiais. Voc gostaria de ver todas as suas modificaes em uma seo contnua e depois todas as modificaes oficiais. Este um trabalho para git rebase conforme descrito acima. Em muitos casos pode se usar a opo -onto e evitar sua interao. Veja tambm git help rebase com exemplos detalhados deste incrvel comando. Voc pode dividir commit. Ou at reorganizar branch de uma rvore.

Reescrevendo o histrico
Eventualmente, ser necessrio que seu controle de cdigo tenha algo equivalente ao modo Stanlinesco de retirada de pessoas das fotos oficiais, apagando-os da histria. Por exemplo, suponha que temos a inteno de lanar um projeto, mas este envolve um arquivo que deve ser mantido privado por algum motivo. Talvez eu deixe meu numero do carto de crdito num arquivo texto e acidentalmente adicione-o ao projeto. Apaga-lo insuficiente, pois, pode ser acessado pe-

28

Lies De Historia

los commit anteriores. Temos que remover o arquivo de todos os commit:


$ git filter-branch --tree-filter 'rm meu/arquivo/secreto' HEAD

Veja git help filter-branch, que discute este exemplo e mostra um mtodo mias rpido. No geral, filter-branch permite que voc altere grandes sees do histrico s com um comando. Depois, voc deve substituir os clones do seu projeto pela verso revisada se desejar interagir com eles depois.

Fazendo histria
Quer migrar um projeto para Git? Se ele for gerenciado por um algum dos sistemas mais conhecidos, ento possvel que algum j tenha escrito um script para exportar todo o histrico para o Git. Seno, de uma olhada em git fast-import, que l um texto num formato especifico para criar o histrico Git do zero. Normalmente um script usando este comando feito as pressas sem muita frescura e executado uma vez, migrando o projeto de uma s vez. Por exemplo, cole a listagem a seguir num arquivo temporrio, como /tmp/history:
commit refs/heads/master committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000 data <<EOT Initial commit. EOT M 100644 inline hello.c data <<EOT #include <stdio.h> int main() { printf("Hello, world!\n"); return 0; } EOT commit refs/heads/master committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800 data <<EOT Replace printf() with write(). EOT M 100644 inline hello.c data <<EOT #include <unistd.h> int main() { write(1, "Hello, world!\n", 14); return 0; } EOT

Magia Git

29

Em seguida crie um repositrio Git a partir deste arquivo temporrio digitando:


$ mkdir projeto; cd projeto; git init $ git fast-import < /tmp/history

Faa um checkout da ltima verso do projeto com:


$ git checkout master .

O comando git fast-export converte qualquer repositrio para o formato do git fast-import, cujo resultado voc pode estudar para escrever seus exportadores, e tambm para transpor repositrios Git para um formato legvel aos humanos. Na verdade, estes comandos podem enviar repositrios de aquivos de texto por canais exclusivamente textuais.

Onde tudo comeou a dar errado?


Voc acabou de descobrir uma funo errada em seu programa, que voc sabe com certeza que estava funcionando h alguns meses atrs. Merda! Onde ser que este erro comeou? Se s voc estivesse testando a funcionalidade que desenvolveu. Agora tarde pra reclamar. No entanto, se voc estiver fazendo commit, o Git pode localizar o problema:
$ git bisect start $ git bisect bad SHA1_DA_VERSAO_ERRADA $ git bisect good SHA1_DA_VERSAO_CERTA

O Git verifica um estado intermedirio entre as duas verses. Testa a funo, e se ainda estiver errada:
$ git bisect bad

Seno, substitua bad por good. O Git novamente o levar at um estado intermedirio entre as verses definidas como good e bad, diminuindo as possibilidades. Aps algumas iteraes, esta busca binria o guiar at o commit onde comeou o problema. Uma vez terminada sua investigao, volte ao estado original digitando:
$ git bisect reset

Ao invs de testar todas as mudanas manualmente, automatize a busca com:


$ git bisect run COMANDO

O Git usa o valor de retorno do comando utilizado, normalmente um nico script, para decidir se uma mudana good ou bad: o comando deve terminar retornando com o cdigo 0 se for good, 125 se a mudana for ignorvel e qualquer

30

Lies De Historia

coisa entre 1 e 127 se for bad. Um valor negativo abortar a bisseco. Pode se fazer muito mais: a pgina de ajuda explica como visualizar bisseces, examinar ou reproduzir o log da bisseco, e eliminar mudanas conhecidamente inocentes para acelerar a busca.

Quem Fez Tudo Dar Errado?


Tal como outros sistema de controle de verses, o Git tem um comando blame (culpado):
$ git blame ARQUIVO

que marca cada linha do arquivo indicado mostrando quem o modificou por ltimo e quando. Ao contrrio de outros sistemas de controle de verses, esta operao ocorre offline, lendo apenas do disco local.

Experincia pessoal
Em em sistema de controle de verses centralizado, modificaes no histrico so operaes difceis, e disponveis apenas para administradores. Clonagem, branch e merge so impossveis sem uma rede de comunicao. Restando as operaes bsicas: navegar no histrico ou fazer commit das mudanas. Em alguns sistemas, exigido do usurio um conexo via rede, apenas para visualizar suas prprias modificaes ou abrir um arquivo para edio. Sistemas centralizados impedem o trabalho offline, e exigem um infraestrutura de rede mais cara, especialmente quando o numero de desenvolvedores aumenta. Mais importante, todas a operaes so mais lentas, at certo ponto, geralmente at o ponto onde os usurios evitam comandos mais avanados at serem absolutamente necessrios. Em casos extremos, esta a regra at para a maioria dos comandos bsicos. Quando os usurios devem executar comandos lento, a produtividade sofre por causa de uma interrupo no fluxo de trabalho. J experimentei este fenmeno na pele. O Git foi o primeiro sistema de controle de verses que usei. E rapidamente cresci acostumado a ele, tomando muitas de suas caractersticas como garantia. Simplesmente assumi que os outros sistemas eram semelhante: escolher um sistema de controle de verses deveria ser igual a escolher um novo editor de texto ou navegador para internet. Fiquei chocado quando, posteriormente, fui forado a usar um sistema centralizado. Minha, frequentemente ruim, conexo com a internet pouco importa com o Git, mas torna o desenvolvimento insuportvel quando precisa ser to confivel quanto o disco local. Alm disso, me condicionava a evitar determinados comandos devido a latncia envolvida, o que me impediu, em ultima instancia, de conti-

Magia Git

31

nuar seguindo meu fluxo de trabalho. Quando executava um comando lento, a interrupo na minha linha de pensamento causava um enorme prejuzo. Enquanto espero a comunicao com o servidor concluir, fao algo para passar o tempo, como checar email ou escrever documentao. No hora em retorno a tarefa original, o comando j havia finalizado a muito tempo, e perco mais tempo lembrando o que estava fazendo. Os seres humanos so ruins com trocas de contexto. Houve tambm um interessante efeito da tragdia dos comuns22: antecipando o congestionamento da rede, os indivduos consomem mais banda que o necessrio em varias operaes numa tentativa de reduzir atrasos futuros. Os esforos combinados intensificam o congestionamento, encorajando os indivduos a consumir cada vez mais banda da prxima vez para evitar os longos atrasos.

22 http://pt.wikipedia.org/wiki/Tragdia_dos_comuns

32

Gro-Mestre Git

Gro-Mestre Git
Este capitulo de nome pomposo minha lixeira para truques do Git no classificados.

Disponibilizao de Cdigo
Para meus projetos, o Git organiza exatamente os arquivos que quero guardar e disponibilizar para os usurios. Para criar um tarball do cdigo fonte, executo:
$ git archive --format=tar --prefix=proj-1.2.3/ HEAD

Gerao do Registro das Modificaes


Uma boa pratica manter um registro das modificaes23, e alguns projetos o exigem. Se voc faz commit com frequncia, e voc deveria fazer, gere um registro das modificaes digitando:
$ git log > ChangeLog

Git por SSH, HTTP24


Suponha que voc tenha acesso ssh ao servidor web, mas o Git no est instalado. Embora menos eficiente que o seu protocolo nativo, o Git pode comunicar sobre HTTP. Baixe, compile e instale o Git na sua conta, e cria um repositrio no seu diretrio web:
$ GIT_DIR=proj.git git init

No diretrio proj.git, execute:


$ git --bare update-server-info $ chmod a+x hooks/post-update

Do seu computador, faa um push via ssh:


$ git push servidor.web:/caminho/para/proj.git master

os outros pegam seu projeto via:


$ git clone http://servidor.web/proj.git
23 http://pt.wikipedia.org/wiki/Changelog 24 http://pt.wikipedia.org/wiki/Http

Magia Git

33

Git Acima de Tudo


Quer sincronizar repositrios sem usar servidores ou mesmo uma conexo via rede? Precisa improvisar durante uma emergncia? J vimos que com o git fast-export e o git fast-import podemos converter repositrios para um nico arquivo e vice-versa. Podemos armazenar estes arquivos de qualquer jeito para transportar nossos repositrios sobre qualquer meio, porm a ferramenta mais eficiente o git bundle. Para o remetente cria um bundle (pacote):
$ git bundle create nomedopacote HEAD

e ento envia o bundle, nomdepacote, para outro lugar usando o que quiser: email, pendrive, disquete, uma impresso xxd25 e um scanner com OCR, lendo bits pelo telefone, sinais de fumaa, etc. O destinatrio recupera os commit do bundle digitando:
$ git pull nomedopacote

O destinatrio pode fazer isto at num repositrio vazio. Apesar do seu tamanho, nomedopacote contm todo o repositrio Git original. Em projetos grandes, diminua os resduos empacotando apenas as mudanas que esto faltando no outro repositrio:
$ git bundle create nomedopacote HEAD ^COMMON_SHA1

Se realizado com frequncia, algum pode esquecer a partir de qual commit deve ser enviado. A pagina de ajuda sugere o uso de tags para resolver isso. Ou seja depois de enviar um bundle, digite:
$ git tag -f ultimobundle HEAD

e crie um novo bundle com as novidades:


$ git bundle create novobundle HEAD ^ultimobundle

Commit do que Mudou


Mostrar ao Git quando adicionamos, apagamos e/ou renomeamos arquivos pode ser problemtico em alguns projetos. Em vez disso, voc pode digitar:
$ git add . $ git add -u

O Git analisar os arquivos no diretrio atual e trabalhar nos detalhes, automa25 http://linux.die.net/man/1/xxd

34

Gro-Mestre Git

ticamente. No lugar do segundo comando add, execute git commit -a se sua inteno efetuar um commit neste momento. Voc pode executar isto em apenas um passo com:
$ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove

As opes -z e -0 previnem contra os transtornos de arquivos com caracteres estranhos no nome. Note que este comando adiciona os arquivos ignorados. Logo, voc pode querer usar as opes -x ou -X.

Meu Commit To Grande!


Voc esqueceu de fazer commit por um muito tempo? Ficou codificando furiosamente e esqueceu do controle de verses at agora? Fez uma srie de modificaes no relacionadas entre si, pois este seu estilo? No se preocupe, Execute:
$ git add -p

Para cada modificao realizada, o Git mostrar o pedao do cdigo alterado, e perguntar se ele deve fazer parte do prximo commit. Responda y (sim) ou n (no). H outras opes, como o adiamento dessa deciso; digite ? para aprender como. Uma vez satisfeito, digite:
$ git commit

para fazer um commit, exato, com as modificaes aprovadas (staged). Lembre-se de retirar a opo -a, caso contrrio o commit conter todas as modificaes. E se voc tiver editado vrios arquivos em vrios locais? Rever cada modificao uma por uma ser frustante e enfadonho. Neste caso, use git add -i, cuja interface menos simples, porm mais flexvel. Com algumas poucas teclas, voc pode aprovar ou no vrios arquivos de uma vez, ou rever e selecionar as modificaes em um arquivos especifico. Alternativamente, execute git commit --interactive o que automaticamente efetuar seus commit assim que terminar de aprovar.

Magia Git

35

No perca a CABEA (HEAD)


A etiqueta HEAD (cabealho) como um indicador que normalmente aponta para o ltimo commit, avanando a cada novo commit. Alguns comandos do Git permitem move-la. Por exemplo:
$ git reset HEAD~3

ir mover o HEAD trs commit pra trs. Assim todos os comandos do Git passam a agir como se voc no tivesse realizados os ltimos trs commit, enquanto seus arquivos permanecem no presente. Consulte a pagina do manual do comando git reset para mais aplicaes. Mas como se faz para voltar para o futuro? Os ltimos commit no sabem do futuro. Se voc tem o SHA1 do HEAD original ento:
$ git reset SHA1

Mas suponha que voc no tenha anotado. No se preocupe, para comandos desse tipo, o Git salva o HEAD original com uma etiqueta chamada de ORIG_HEAD, e voc pode retornar so e salvo com:
$ git reset ORIG_HEAD

Explorando o HEAD
Talvez ORIG_HEAD no seja suficiente. Talvez voc s tenha percebido que fez um erro descomunal e precisa voltar para um antigo commit de um branch h muito esquecido. Na configurao padro, o Git mantm um commit por pelo menos duas semanas, mesmo se voc mandou o Git destruir o branch que o contm. O problema achar o hash certo. Voc pode procurar por todos os volares de hash em .git/objects e por tentativa e erro encontrar o que procura. Mas h um modo mais fcil. O Git guardar o hash de todos os commit que ele calcula em .git/logs. O sub-diretrio refs contm o histrico de toda atividade em todos os branch, enquanto o arquivo HEAD mostra todos os valores de hash que teve. Este ltimo pode ser usado para encontrar o hash de um commit num branch que tenha sido acidentalmente apagado. O comando reflog fornece uma interface amigvel para estes arquivos de log. Experimente

36
$ git reflog

Gro-Mestre Git

Ao invs de copiar e colar o hash do reflog, tente:


$ git checkout "@{10 minutes ago}"

Ou faa um checkout do ante-ante-ante-antepenltimo commit com:


$ git checkout "@{5}"

Leia a seo Specifying Revisions da ajuda com git help rev-parse para mais informaes. Voc pode querer configurar um longo perodo de carncia para condenar um commit. Por exemplo:
$ git config gc.pruneexpire "30 days"

significa que um commit apagado ser permanentemente eliminado aps se passados 30 dias e executado o comando git gc. Voc tambm pode desativar as execues automticas do git gc:
$ git conifg gc.auto 0

assim os commit s sero permanentemente eliminados quando executado o git gc manualmente.

Baseando se no Git
Seguindo o jeito UNIX26 de ser, o Git permite ser facilmente utilizado como um componente de baixo nvel para outros programas. Existem interfaces GUI, interfaces web, interfaces alternativas para linha de comando e talvez em breve voc crie um script ou dois para suas necessidades usando o Git. Um truque simples criar alias, abreviaes, internos ao Git para reduzir os comandos utilizados mais frequentemente:
$ git config --global alias.co checkout $ git config --global --get-regexp alias alias.co checkout $ git co foo # exibe os alias criados # o mesmo que 'git checkout foo'

Outra imprimir o branch atual no prompt, ou no ttulo da janela. s invocar


$ git symbolic-ref HEAD

mostra o nome do branch atual. Na prtica, muito provavelmente voc no


26 http://pt.wikipedia.org/wiki/Unix

Magia Git

37

quer ver o /refs/heads e ignorar os erros:


$ git symbolic-ref HEAD 2> /dev/null | cut -b 12-

Veja a pgina do Git para mais exemplos.

Dubls Duros na Queda


As verses recentes do Git tornaram mais difcil para o usurio destruir acidentalmente um dado. Esta talvez o principal motivo para uma atualizao. No entanto, h vezes em que voc realmente quer destruir um dado. Mostraremos maneiras de transpor estas salvaguardas para os comandos mais comuns. Use-as apenas se voc sabe o que esta fazendo. Checkout: Se h modificaes sem commit, um checkout simples falhar. Para destruir estas modificaes, e fazer um checkout de um certo commit assim mesmo, use a opo force (-f):
$ git checkout -f COMMIT

Por outro lado, se for especificado algum endereo em particular para o checkout, ento no haver checagem de segurana. O endereo fornecido ser silenciosamente sobrescrito. Tenha cuidado se voc usa o checkout desse jeito. Reset: O Reset tambm falha na presena de modificaes sem commit. Para obriga-lo, execute:
$ git reset --hard [COMMIT]

Branch: Apagar um branch falha se isto levar a perda das modificaes. Para forar, digite:
$ git branch -D BRANCH # ao invs de usar -d

Analogamente, a tentativa de sobrescrever um branch movendo-o falha for causar a perda de dados. Para forar a movimentao do branch, use:
$ git branch -M [ORIGEM] DESTINO # ao invs de usar -m

Ao contrrio do checkout e do reset, estes dois comandos adiaro a destruio dos dados. As modificaes ainda sero armazenadas no subdiretrio .git, e podem ser resgatados, recuperando o hash apropriado do .git/logs (veja a seo "Explorando o HEAD" acima). Por padro, eles sero mantidos por pelo menos duas semanas. Clean: Alguns comandos do Git recusam-se a avanar devido o receio de sobrescrever arquivos no monitorados (sem commit). Se voc tiver certeza de que todos os arquivos e diretrios no monitorados so dispensveis, ento apa-

38 gue-os sem misericrdia com:


$ git clean -f -d

Gro-Mestre Git

Da prxima vez, o maldito comando no se recusar a funcionar!

Magia Git

39

Segredos Revelados
Vamos dar uma espiada sob o capo e explicar como o Git realiza seus milagres. Ser uma explicao superficial. Para detalhes mais aprofundados consultar o manual do usurio27.

Invisibilidade
Como pode o Git ser to discreto? Fora ocasionais commit e merge, voc pode trabalhar como se desconhecesse que existe um controle de verses. Isto , at que precise dele, e quando voc ficar agradecido ao Git por estar vigiando o que faz o tempo todo. Outros sistemas de controle de verses no deixam voc esquece-los. As permisses dos arquivos so apenas de leitura, a menos que voc diga ao servidor quais arquivos tem a inteno de editar. O servidor central estar monitorando as aes de quem fez o checkout e quando. Quando a rede cair, voc ter um sofrimento repentino. Desenvolvedores constantemente brigam com a burocracia e a burrocracia virtual. O segredo o diretrio .git no seu diretrio de trabalho. O Git guarda o histrico do seu projeto nele. O . no inicio do nome esconde ele de uma listagem ls normal. Exceto quando voc esta fazendo um push ou pull das modificaes, todas as operaes de controle de verses so neste diretrio. Voc tem controle total sobre o destino dos seus arquivos pois o Git no se importa com o que faz a eles. O Git pode facilmente recriar um estado salvo a partir do .git a qualquer hora.

Integridade
A maioria das pessoas associam criptografia com manter informaes secretas, mas outra aplicao igualmente importante manter a integridade da informao. O uso correto das funes criptogrficas de hash podem prevenir o corrupo acidental ou intencional dos dados. Um hash SHA1 pode ser entendido como um nmero identificador nico de 160 bits para cada sequncia de bytes que voc vai encontrar na vida. Na verdade mais que isso: para cada sequncia de bytes que qualquer ser humano jamais usar durante vrias vidas. O hash de todo o contedo de um arquivo pode ser visto como um identificador nico para o mesmo.
27 http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

40

Segredos Revelados

Uma observao importante que um hash SHA1 , ele mesmo, uma sequncia de bytes, assim ns podemos gerar um hash de sequncias de bytes formada por outros hash. A grosso modo, todos os arquivos manipulados pelo Git so referenciados pelo seu identificador nico, e no por seu nome. Todos os dados esto em arquivos no subdiretrio .git/objects, onde no h nenhum arquivo com nomes normais. O contedo so sequncias de bytes chamados de blob e eles no tem relao com seus nomes. Seus nomes so registrados em outro lugar. Eles esto nos objetos tree, que so listas dos nomes dos arquivos formados com os identificadores de seus contedos. Uma vez que o tree uma sequncia de bytes, ele tambm tem um identificador nico, que como ele armazenado no subdiretrio .git/objects. Objetos Tree podem aparecer na lista de outro tree, logo, um diretrio tree e todos os seus arquivos podem representados por objetos tree e blob. Finalmente, um commit contm um mensagem, alguns identificadores tree e a informao de como eles esto relacionados entre si. Um commit tambm um sequncia de bytes, logo, possui um identificador nico. Veja voc mesmo: pegue qualquer hash do diretrio .git/objects, digite
$ git cat-file -p SHA1_HASH

Agora suponha que algum tenta reescrever o histrico e tenta modificar o contedo de um arquivo de uma verso antiga. Ento o identificador nico do arquivo sofrer modificaes j que agora ele uma sequncia de bytes diferente. Isto modifica o identificador de qualquer objeto tree referente a este arquivo, que por sua vez modifica o identificador de todos os objetos commit envolvendo este tree. A corrupo do repositrio ruim exposta quando todos recebem todos os commit j que o arquivo manipulado tem o identificador errado. Ignorei detalhes como as permisses e assinaturas do arquivo. Mas, em suma, enquanto os 20 bytes representando o ltimo commit forem seguro, impossvel de enganar um repositrio Git.

Inteligncia
Como o Git sabe que um arquivo foi renomeado, mesmo se voc nunca mencionou o fato explicitamente? Com certeza, voc executou git mv, mas isto exatamente o mesmo que um git rm seguido por um git add. A analise heurstica do Git verifica alm das aes de renomear e de copias sucessivas entre verses. De fato, ele pode detectar pedaos de cdigo sendo movidos ou copiados entre arquivos! Embora no cubra todos os casos, faz um traba-

Magia Git

41

lho decente, e esta caracterstica est sendo sempre aprimorada. Caso no funcione com voc, tente habilitar opes mais refinadas para deteco de cpias e considere uma atualizao.

Indexando
Para cada arquivo monitorado, o Git armazena informaes como: tamanho, hora de criao e ltima modificao, em um arquivo conhecido como index. Para determinar se um arquivo foi modificado, o Git compara seus status atual com o que tem no index. Se coincidem, ento ele pode ignorar o arquivo. J que verificaes de status so imensamente mais baratas que ler o contedo do arquivo, se voc editar poucos arquivos, o Git vai atualizar seus status quase que instantaneamente.

Repositrios Crus
Voc pode estar imaginando que formato o repositrio online do Git usa. Eles so repositrios Git simples, iguais ao seu diretrio .git, exceto que eles tem nomes como proj.git, e no tem nenhum diretrio de trabalho associado a eles. A maioria dos comandos do Git esperam que o index do Git esteja no .git, e falharo nos repositrios crus. Corrija isto configurando a varivel de ambiente GIT_DIR com o caminho do seu repositrio cru, ou executando o Git a partir deste diretrio com a opo --bare.

Origem do Git
Esta mensagem na lista de discuo do Linux Kernel28 descreve a sequncia de eventos que levaram ao Git. A discusso inteira um sitio arqueolgico fascinante para historiadores do Git.

28 http://lkml.org/lkml/2005/4/6/121

42

Atalhos Do Git

Atalhos Do Git
H algumas questes sobre o Git que joguei pra debaixo do tapete. Algumas so facilmente tratadas com script e gambiarras, algumas requerem uma reorganizao ou redefinio do projeto, e para as poucas chateaes remanescentes, s resta espera por uma soluo. Ou melhor ainda, solucione-as e ajude a todos! Estive brincando com algumas ideias para sistemas de controle de verses, e escrevi um sistema experimental baseado no Git29, que aborda algumas desses questes.

Microsoft Windows
O Git no Microsoft Windows pode ser trabalhoso: Cygwin30, um ambiente que deixa o Windows parecido com o Linux, tem uma verso do Git para Windows31. Git no MSys32 um alternativa que requer suporte minimo para execuo, embora alguns poucos comandos precisem ser mais trabalhados.

Arquivos Independentes
Se seu projeto muito grande e tem muitos arquivos independentes que esto sendo constantemente modificados, o Git pode ser prejudicado mais do que outros sistemas, pois os arquivos no so monitorados isoladamente. O Git monitora modificaes no projeto como um todo, o que geralmente benfico. Uma soluo dividir seu projeto em pedaos, cada um composto de arquivos relacionados. Use git submodule se ainda quiser manter tudo num repositrio s.

Quem Est Editando O Que?


Alguns sistemas de controle de verses iro fora-lo a explicitamente marcar um arquivo de alguma maneira antes de edita-lo. Embora seja especialmente irritante quando isso envolve usar um servidor centralizado, isto tem dois benefcios: 1. Diff so rpido pois apenas os arquivos marcados so examinados;
29 http://www-cs-students.stanford.edu/~blynn/gg/ 30 http://cygwin.com/ 31 http://cygwin.com/packages/git/ 32 http://code.google.com/p/msysgit/

Magia Git

43

2. Outros podem saber quem est trabalhando no arquivo perguntando ao servidor central quem marcou o arquivo para edio. Com o script certo, voc pode fazer o mesmo com o Git. Isto requer apenas a cooperao dos programadores, que devem executar o script em particular quando estiver editando um arquivo.

Arquivo do Histrico
Assim que o Git armazena modificaes muito amplas no projeto, reconstruir o histrico de um nico arquivo requer mais trabalho do que em sistemas de arquivos de monitoram arquivos individualmente. A penalidade usualmente rpida, e vale a pena devido a eficincia que d s outras operaes. Por exemplo, git checkout to rpido quanto cp -a, e os deltas que abrangem grandes partes do projeto tem uma compresso melhor do que os deltas de agrupamentos de arquivos.

Clone Inicial
A criao de um clone mais trabalhoso do que fazer checkout em outros sistemas de controle de verses quando h um histrico grande. O custo inicial se paga a longo prazo, pois as futuras operaes sero mais rpidas e offline. Entretanto, em algumas situaes, prefervel criar um clone oco com a opo --depth. Isto muito mais rpido, porm resulta em um clone com funcionalidades reduzidas.

Projetos Volteis
O Git foi feito para ser rpido no que diz respeito ao tamanho das mudanas. Humanos fazem poucas edies de verso pra verso. a correo de uma falha numa linha, uma nova caracterstica do sistema, incluso de comentrio e assim por diante. Mas se seus arquivos diferem muito de uma verso para outra, em cada commit, seu histrico ir crescer acompanhando o tamanho do seu projeto todo. No h nada que qualquer sistema de controle de verses possa fazer pra ajudar, mas os usurios padres do Git devem sofrer mais quando estiverem clonando histricos. As razes pelas quais as mudanas so to grandes, devem ser analisadas. Talvez os formatos dos arquivos possa ser trocado. Edies menores s devem causar pequenas modificaes em poucos arquivos.

44

Atalhos Do Git

Ou talvez um banco de dados ou uma soluo de backup/arquivamento seja o que voc realmente precisa, e no um sistema de controle de verses. Por exemplo, um controle de verses pode ser adequado para gerenciar fotos feitas periodicamente de uma webcam. Se os arquivos esto, realmente, mudando constantemente e precisam ser versionados, uma possibilidade usar o Git de uma maneira centralizada. Pode-se criar clones ocos, que adiciona pouco ou quase nada ao histrico do projeto. claro, que muitas ferramentas do Git se tronaram inadequadas, correes devem ser enviadas como patch. Isto deve ser razoavelmente til, para algum que deseja manter um histrico de arquivos demasiadamente instveis. Outro exemplo um projeto dependente de firmware, o qual provavelmente estar em grande arquivo binrio. O histrico de arquivos de firmware irrelevante para os usurios, e as atualizaes tm uma pssima compresso, assim revises de firmware estouraro o tamanho do repositrio sem necessidade. Neste caso, o cdigo fonte deve ser armazenado num repositrio Git, e os arquivos binrios mantidos separados do mesmo. Para facilitar o trabalho, algum cria e distribui um script que usa o Git para clonar o cdigo e o rsync ou um clone oco do Git para o firmware.

Contador Global
Alguns sistemas centralizados de controle de verses mantm um nmero inteiro positivo que incrementado quando um novo commit aceito. O Git referencia as modificaes por seus hash, o que o melhor na maioria circunstncias. Mas algumas pessoas gostariam de ter este nmero por perto. Felizmente, fcil criar um script que faa isso a cada atualizao, o repositrio central do Git incrementa o nmero, ou talvez uma marca, e associa a mesma com o hash do ltimo commit. Cada clone poderia gerenciar este contador, porm isto provavelmente seja desnecessrio, j que apenas o contador do repositrio central que importar para todos.

Subdiretrios Vazios
Subdiretrios vazios no so monitorados. Crie arquivos vazios para resolver esse problema. A atual implementao do Git, e no seu o design, a razo deste inconveniente. Com sorte, uma vez que o Git ganhe mais trao, mais usurios devem clamar por esse recurso e ele poder ser implementado.

Magia Git

45

Commit Inicial
Um cientista da computao tipico inicia uma contagem do 0, ao invs do 1. Entretanto, no que diz respeito a commit, o Git no segue esta conveno. Muito comandos so confusos antes do commit inicial. Alm disso existem algumas arestas que precisam aparadas manualmente, seja com um rebase de um branch com um commit inicial diferente. H benefcios ao Git por definir o commit zero: assim que um repositrio construdo, o HEAD ser definido para uma sequncia constituda de 20 bytes zero. Este commit especial representa um tree vazio, sem predecessor, num momento anterior a todos os repositrios Git. Se em seguida for executado por exemplo, o git log, ser informado ao usurio que ainda no foi realizado nenhum commit, ao invs de terminar devido um erro fatal. Similar a outras ferramentas. Todos commit inicial implicitamente um descendente deste commit zero. Por exemplo, fazendo um rebase num branch no monitorado pode ocasionar um enxerto de todo o branch no destino. Atualmente, todos, inclusive o commit inicial, sero enxertados, resultando num conflito de merge. Uma soluo usar git checkout seguido de git commit -C no commit inicial, e um rebase no restante. Infelizmente h casos piores. Se vrios branch com diferentes commit iniciais forem mesclados (merge), ento um rebase do resultado vai requer uma substancial interveno manual.

Você também pode gostar