Peepcode sponsors akitaonrails.com Locaweb sponsors akitaonrails.com

Git com Sake

AkitaOnRails / 03.Apr.2008 at 01:02pm

Se vocês ainda não sabem muito bem como usar o Git no dia-a-dia, recomendo primeiro ler meu micro-tutorial de Git.

Muito bem, a primeira reclamação que eu sempre ouço é a falta de suporte a Windows. Não tem equivalente a TortoiseSVN, precisa instalar Cygwin pra usar git-svn. Blá blá. So sorry guys. Existem 3 opções: usar no Cygwin, que funciona bem. Instalar uma virtual machine linux com VMWare ou coisa que o valha. Parar de reclamar e, no bom espírito open source, tentar contribuir de volta. Não sei para que as reclamações. O problema não é reclamar, o problema é a atitude de ‘eu sou importante e vocês precisam fazer do jeito que eu gosto’. Bom, pare de usar open source se este for o caso. Não é suficiente já estarmos usando ferramentas de graça?

De volta ao ponto, a segunda reclamação é: o Git tem mais de 140 comandos diferentes! Isso é coisa pra caramba! Mas sejamos realistas, no dia-a-dia de desenvolvimento – se você não for um programador hard-core – precisará sempre da mesma meia dúzia de comandos.

No meu micro-tutorial, depois de já fazer clone do repositório online, eu falei do seguinte fluxo:

  • git checkout -b meu_branch
  • (trabalhar trabalhar trabalhar)
  • git add .
  • git commit -a -m “meu comentário”
  • git checkout master
  • git merge meu_branch
  • git push (ou git svn dcommit)

No fluxo acima estou fazendo o seguinte:

  • Criando um branch chamado ‘meu_branch’
  • (trabalhar trabalhar trabalhar)
  • Adicionando novos arquivos que eu tenha criado
  • Fazendo o commit com a descrição, tudo no ‘meu_branch’
  • Voltando ao branch original ‘master’
  • Trazendo as modificações que fiz commit, do ‘meu_branch’ para o ‘master’
  • Enviando as modificações do ‘master’ para o repositório Git (ou para o Subversion caso eu tenha feito git svn clone, no começo)

E se algum desenvolvedor também enviou mudanças ao repositório online e você quer trazê-las para seu repositório local?

  • git checkout master
  • git pull (ou git svn fetch e git svn rebase)
  • git checkout meu_branch
  • git rebase master

O que estou fazendo? Vamos lá:

  • Voltando ao branch ‘master’ caso eu já não esteja lá
  • Puxando as modificações do servidor (se o servidor for SVN, são dois comandos, fetch e rebase)
  • Voltando ao ‘meu_branch’
  • Sincronizando ‘meu_branch’ com as modificações que chegaram ao ‘master’

Esse é o fluxo de trabalho mais comum. As outras duas operações mais comuns são:

  • git checkout -b ‘meu_branch’
  • git branch -d ‘meu_branch’

Literalmente, criar um branch e apagar um branch. Aliás, essa é uma das características de todo bom gerenciador de código decentralizado: criar branches é uma rotina, não uma exceção como é no Subversion. Crie quantos branches quiser, use e abuse. No Git, criar branches é barato e fazer merges entre branches também é barato! No SVN, criar branches é barato, mas fazer os merges e manipular esses branches é trabalhoso o suficiente para você reservar um dia inteiro só para isso.

Agora, dos +140 comandos do Git, para o dia-a-dia de um humilde desenvolvedor, eu preciso apenas de cerca de 10 comandos. Nada mal, mas será que podemos fazer melhor?

Git on Sake!

Voltemos ao caso onde acabei de fazer um git clone (ou git svn clone). Quero criar um branch, começar a trabalhar, puxar novidades do repositório, enviar minhas modificações de volta ao repositório e apagar o branch temporário que criei. Como faço?

  • sake git:open
  • (trabalhar trabalhar trabalhar)
  • sake git:update
  • (trabalhar trabalhar trabalhar)
  • sake git:push
  • sake git:close

Pronto. 4 comandos, que tal?

O que estamos fazendo é usando o Sake. Todo mundo já conhece Rake, que é um gerenciador de tarefas. O Rake se ocupa com tarefas exclusivas do projeto em que você está no momento. Já o Sake é como se fosse um “Rake global”. Ele lê as tarefas do arquivo ~/.sake e funciona de qualquer diretório de onde você estiver. Para instalar o sake, é o básico:

sudo gem install sake

Sobre isso, o Brian Donovan publicou em seu blog um conjunto de tasks Sake para facilitar o trabalho o Git.

Eu fiz uma pequena alteração no código dele para que o task de ‘push’ faça o merge do ‘meu_branch’ de volta ao ‘master’ antes de enviar as modificações do ‘master’ para o servidor online, fechando meu workflow diário perfeitamente.

Para instalar, basta fazer o seguinte:

sake -i http://pastie.caboo.se/175145.txt

Isso mesmo! O Sake instala tarefas a partir de arquivos locais ou até mesmo de URLs!

Pois é, alguns reclamam: “Os comandos do Git são muito difíceis …” Buá buá buá

Outros solucionam o problema. É como eu sempre digo se você não faz parte da solução, então faz parte do problema.

Pronto, é tudo que você precisa para começar a desenvolver usando Git com a mesma facilidade de sintaxe de comandos que o Subversion! E para quem quiser uma cópia do script (caso aconteça alguma coisa com a cópia no Pastie), aqui vai:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

namespace :git do
  task :helpers do
    def git_branch
      `git branch | grep "*"`.strip[2..-1]
    end
    
    def git?
      `git status`
      $?.exitstatus != 128
    end
    
    def git_stash
      `git diff-files --quiet`
      if $?.exitstatus == 1
        stash = true
        clear = `git stash list`.scan("\n").size == 0
        puts "* Saving changes..."
        `git stash save`
      else
        stash = false
      end
      
      begin
        yield
      rescue
        puts "* Encountered an error, backing out..."
      ensure
        if stash
          puts "* Applying changes..."
          sh "git stash apply"
          `git stash clear` if clear
        end
      end
    end
    
    def git_fetch
      sh "git#{'-svn' if git_svn?} fetch"
    end
    
    def git_rebase
      if git_svn?
        sh "git rebase git svn"
      else
        sh "git rebase origin/master"
      end
    end
    
    def git_push
      if git_svn?
        sh "git svn dcommit"
      else
        sh "git push"
      end
    end
    
    def git_svn?
      `git branch -a` =~ /^\s*git svn/
    end
  end
  
  desc "Pull new commits from the repository"
  task :update => %w[git:helpers] do
    git_stash do
      branch = git_branch()
      if branch != "master"
        switch = true
        `git checkout master`
        puts "* Switching back to master..."
      else
        switch = false
      end

      puts "* Pulling in new commits..."
      git_fetch
      git_rebase
    
      if switch
        puts "* Porting changes into #{branch}..."
        `git checkout #{branch}`
        sh "git rebase master"
      end
    end
  end
  
  desc "Push local commits into the Wesabe repository"
  task :push => %w[git:update] do
    git_stash do
      puts "* Pushing changes..."
    
      branch = git_branch()
      if branch != "master"
        puts "Pushing changes from #{branch} into master"
        `git checkout master`
        `git merge #{branch}`
        puts "Pushing changes from master into server"
        git_push
        puts "Going back to #{branch}"
        `git checkout #{branch}`
        `git rebase master`
      else
        puts "Pushing changes from master into server"
        git_push        
      end
    end
  end
  
  desc "Delete the current branch and switch back to master"
  task :close => %w[git:helpers] do
    branch = git_branch()
    if branch == "master"
      $stderr.puts "* Cannot delete master branch"
      exit 1
    end
    
    puts "* Switching to master"
    `git checkout master 2>/dev/null`
    puts "* Deleting branch #{branch}"
    `git branch -d #{branch} 2>/dev/null`
    if $?.exitstatus == 1
      $stderr.puts "* Branch #{branch} isn't a strict subset of master, quitting"
      `git checkout #{branch} 2>/dev/null`
      exit 1
    end
  end
  
  desc "Create a new branch off master"
  task :open => %w[git:helpers] do
    print "* Name your branch: "
    newbranch = $stdin.gets.chomp
    
    branch = git_branch()
    if branch != "master"
      puts "* Switching to master"
      `git checkout master`
    end
    
    `git checkout -b #{newbranch}`
    unless $?.exitstatus.zero?
      puts "* Couldn't create branch #{newbranch}, switchin back to #{branch}"
      `git checkout #{branch}`
      exit 1
    end
  end
end

18 Comments

Boa Akita, agora não tem choro.

[]s

Só um adendo para o pessoal de Windows: agora tem também o msysGit. Não o testei pessoalmente, mas é sempre mencionado nas discussões do Reddit e afins, e alguns dizem já ser um grande avanço em relação ao Cygwin.

Ainda nao instalei o GIT, mas se a reclamação do pessoal é sobre ferramenta UI para GIT no windows acho a coisa mais sem sentido, qual a diferença de fazer a mesma coisa no prompt?

Oi Akita, vc tá virando um evangelizador GIT hein! E Daniel, a diferença é que o pessoal do Windows é acostumado a ter tudo graficamente a dois cliques. A idéia de ter que trabalhar com shell assusta muita gente. Isso é esquisito mas acontece

@Weldys é a velha história de sempre. Em 1996 meu amigos não acharam grande coisa eu estar aprendendo Java. Em 2003 o pessoal reclamou que SVN nunca ia pra frente. Em 2005 ninguém deu a mínima quando comecei a ver Rails. Em 2008 é o caso do Git :-)

Acho que você acerta de novo porque testando a ferramenta Git em uma aplicação que estou desenvolvendo, encontrei muita rapidez, facilidade e boas ferramentas (como o github) no controle do meu código.

Das reclamacoes…:

  • Windows… e isso interessa??? sinceramente nao consigo conceber um programador que tenha a demanda de usar um git que desenvolva em um windows, alias mal consigo associar o nome programador a alguem que vive em uma plataforma onde nao se tem um tail pra ler um log Oo … na melhor das hipoteses se tem uns usuarios de IDE no windows e pra esses (como jah ouvi da boca de alguns inclusive), mal conseguem perceber a diferenca entre o CVS e o SVN!!!
  • Muitos comandos: o git esta alterando isso… futuramente muitos dos comando hj normalmente acessiveis serao movidos do path pra tu nao ter tudo isso lah visivel. Claro que os comandos estarao lah pra serem usados! Na verdade o ponto eh que as pessoas precisam entender pra invalidar esta critica eh que muitos dos “comandos” do git na verdade sao ferramentas que ele mesmo (o git) usa, e estao lah abertos pra ti usar tbm justamente para que tu tenhas a flexibilidade de usar SE necessario. Criticar o fato de que o poder tah lah, me remete a programadores Java, que normalmente tem aquela metalidade de que o poder nao deve estar acessivel: “Nao, nao, nao me mostre todos estes comandos, eu nao consigo viver com sabendo que eles existem!” isso parece bastante com “Nao, nao, nao me fala de heranca multipla, minah cabeca soh aguenta heranca simples e jah apanho pra esse negohcio de interface” :p

Agora eu fazendo reclamacoes (nem acredito que vou fazer isso):

Caralho, o git eh meio geek demais neh?!!

Eh ohbvio que eu adorei isso, heheSe tu quer entender a coisa, de certa forma se espera que tu seja um pouquinho mais do que um code monkey tradicional, hehe… mas…

A maior dificuldade que eu acho com o Git, eh a falta de coisas te orientando em relacao a parte mais administrativa da coisa… Quando tu pensa como desenvolvedor que vai trabalhar na tua workstation e o mais perto da maquina “central” que tu chega eh via push, tudo parece magico, mas!!! (sempre esses mas)

Tenho sentido falta de informacoes praticas sobre o uso do Git em termos admnistrativos… Claro, isso eh consequencia de anos com a mente fechada no SVN e CVS, mas sinceramente gostaria de ter mais documentacoes sobre as experiencias de outros com suas infraestruturas e praticas de uso do Git em equipe.

Eu por exemplo, em minha equipe, resolvi conservar o conceito de servidor centralizando tudo… e comecei BEM mal… Acostumado com meu velho SVN via DAV, lah fui eu, gastei um certo tempinho seguindo o manualzinho do git pra por ele sobre HTTP, contente que eu ia conseguir seguir a mesma mentalidade. Comecei a aplicacao e dalhe commit no treco, jah tava lah bonitinho sendo rastreado pelo nosso tracker, tudo maravilha… ateh que eu lembrei! Esquecei de dar freeze no rails! Freeze feito, comitei local, maravilha…fui fazer o push e deu pate! E aih??? Pesquisa em cima de pesquisa e testando de tudo…nada da porcaria do git voltar… pereguntando pra amigos com BEM mais experiencia no uso do Git, comecei a ver as caras feias… “O que?? Tu usa o servidor pra comitar via HTTP???” “Mas que abominacao!!!”

Moral da historia, tempo perdido! Bem que poderiam ter comentado sobre o fato de que isso NAO eh uma pratica comum!!! Quem sabe eu eh que nao li nos lugares certos, hehe…

Brincadeiras apart, nao eh soh isso… daih vc decide mudar para um ambiente com SSH… comecam mais duvidas… um user ou N users e acl??? Ou, Ou, Ou…

Pois eh, assim eu sigo minha saga aqui… atualmente estou levantando um ambiente com ACL, mas sinceramente a sensacao de que falta documentacao sobre este tipo de coisa no Git fica!

ok, pelomenos jah sei sobre o que escrever quando tomar vergonha na car e publicar um blog…

Ahh!!!...

ainda sobre o windows: e pra quem precisa de NAO programadores que precisam usar o um controlador de versoes, como os designers por exemplo… Para estes vc pode expor seu repositorio GIT como um repositorio CVS e continuar a usar o Tortoise normalmente!!

Bom, ainda na discussão sobre fácil/difícil/ferramentas.

Encontrei um projeto(ainda em desenvolvimento) de um plugin para integrar o Eclipse ao Git. Segue o link: http://git.or.cz/gitwiki/EclipsePlugin

Talvez mais útil para os “javeiros” como diz o Akita, mas é um projeto open que vem para adicionar uma ferramenta visual e multi-plataforma para trabalhar com Git.

Isso já faz dele uma idéia boa. :-D

Vamos ver onde isso vai.

Até mais.

@Everton, você tem razão. Com sorte os artigos sobre isso devem começar a aumentar.

Para quem ficou com dúvida, este artigo e este outro talvez ajudem.

Para desenvolvedores que não querem os problemas de configurar um servidor, o Github ou o Gitorius são as melhores opções de configuração-zero.

@Luis, só pro pessoal não me entender mal: eu não sou contra ferramentas visuais, pelo contrário. Quando eu estava aprendendo SVN, o Tortoise foi uma mão na roda.

Em algumas coisas ele me irritava. Por exemplo, pelo menos na época ele precisava varrer todos os diretórios do projeto lendo os sub-diretórios .svn (cara, como isso me irrita). Em projetos muito grandes, o Tortoise era literalmente uma tartaruga. Para alguns tamanhos de projeto acho que ele é inviável.

O Tortoise instala um serviço chamado TSVNCache para evitar fazer uma varredura brute-force o tempo todo, mas isso também era sacal. Na época ele queria ler tudo. Se eu colocasse um USB drive, o Windows se recusava a ejetar, isso porque o TSVNCache tava lockando ele.

Alguns arquivos também permaneciam lockados e eu não conseguia deletar. Precisava matar o TSVNCache pra fazer isso. Depois acho que fizeram uma opção POG pra reiniciar esse processo pelo menu :-)

Se saírem como um TortoiseGit, com mais performance e sem esses percalços, acho que vai ser uma mão na roda sim.

Mesmo no Linux ou Mac, nós estamos acostumados a usar Gitk, que é uma ferramentinha muito útil para visualizar a vida dos vários branches e commits que temos. No Mac tem o Gitnub (que esta no Github) que torna fácil visualizar as mudanças que aconteceram em cada commit. A coisa está evoluindo.

Fabio: you should have based the git commands on 'git' instead of git-dash kind of commands, that way, compatibility with @git.cmd or git.bat from msysgit are more closer to the cross-platform goal ;-)

Regards.

@Luis, you’re right. I just copied from Brian’s original. I already updated as you suggested. Thanks.

Excelente Akita! Eu estou começando a mexer com GIT e seus artigos ajudam bastante.

Uma outra opção para quem precisa desenvolver em windows é um client PHP para GIT (http://code.google.com/p/git-php/)

Abs.

Thanks for covering this! Your modification to use git-merge instead of rebasing seems like a bad idea, as merge histories are not preserved in SVN. Any thoughts on this?

@Brian, hi there. So, are you sure about that? I am no git specialist either but I’ve been using this procedure exactly for a project interfacing with svn, and in fact I do have all the history in svn as the client is using statsvn to check our development pace. I would lose the history if I used the—squash flag, isn’t it?

A idéia de mostrar os comandos mais usados por você no dia-a-dia GIT foi excelente :-)

Grande abraço!

Fala Akita!

ontem implementei Git pela primeira vez, num servidor com Trac que eu já tinha usava com Bazaar.

o resultado final é fascinante, a performance é muito bacana, mas eu realmente apanhei muito até conseguir entender toda essa parafernália de add -> commit -> commit <remote> -> merge <remote> -> pull , e mais push, init, ssh:, etc

a minha sensação é de que a tarefa mais importante nesse momento é de construção de documentação, tutoriais, grupos de discussão e todo tipo de interação sobre o tema pra encher esse google de informação e esclarecimentos.

por isso mesmo acho q vc está de parabéns por esses tutoriais.

conhece algum grupo de discussão nacional sobre o Git? me convida :)

abraços

Leave a Comment