Git para Usuários do Subversion, Parte 1: Introdução

O Git é desmistificado para os usuários do Version Control System Subversion

Os distributed version control systems (DVCSs) oferecem várias vantagens em relação os VCSs centralizados, e para usuários do Subversion que procuram explorar este modelo, o Git é um excelente lugar para começar. Usando o Subversion como uma linha de base, este primeiro de dois artigos mostra como instalar o Git, configurar um repositório remoto e começar a usar comandos Git básicos.

Teodor ZlatanovGold Software Systems

Teodor Zlatanov surgiu com um Mestrado em Ciências em engenharia da computação da Boston University em 1999. Trabalha como programador desde 1992, usando Perl, Java, C e C++. Seus interesses estão em trabalho em análise de textos de software livre, arquiteturas de banco de dados, interfaces com o usuário e administração do sistema UNIX.



04/Ago/2009

Para qualquer um que não esteja familiarizado com version control systems (VCSs) de software livre, o Subversion se tornou um VCS não comercial padrão, substituindo o antigo campeão, Concurrent Versions System (CVS). O CVS ainda é útil para uso limitado, mas o atrativo do Subversion é que ele requer apenas um pouco de configuração em um servidor da Web e não muito além disso. O Subversion possui alguns problemas, os quais discutirei aqui, mas em sua maior parte, ele funciona bem.

Portanto, por que precisamos de um outro? Git ("G" maiúsculo; git é a ferramenta da linha de comandos) é, em muitos aspectos, projetado para ser melhor que o Subversion. Ele é um dos muitos VCSs distribuídos . Minha própria experiência inicial com o Arch/tla, como também Mercurial, Bazaar, darcs, e alguns outros. Por muitas razões, que discutirei quando forem relevantes, o Git se torna popular e é frequentemente considerado, juntamente com o Subversion, as duas melhores opções para um VCS pessoal ou corporativo.

Há duas razões importantes para estar interessado no Git se você for um usuário do Subversion.

  • Você está querendo mudar para o Git porque o Subversion está limitando você de alguma forma.
  • Você está curioso sobre o Git e deseja descobrir como ele se compara com o Subversion.

Bem, talvez haja uma terceira razão: o Git é uma tecnologia relativamente recente que você deseja incluir em seu currículo. Espero que esse não seja seu principal objetivo; aprender o Git é uma das coisas mais recompensadoras que um desenvolvedor pode fazer. Mesmo se você não usa o Git agora, os conceitos e o fluxo de trabalho incorporado neste VCS distribuído são, certamente, um conhecimento crucial para a maioria dos segmentos do mercado de TI nos próximos 10 anos enquanto o mercado passa por grandes mudanças em escopo e distribuição geográfica.

Finalmente, embora não seja uma razão convincente se você não for um desenvolvedor de kernel Linux, o kernel e uma série de outros projetos importantes são mantidos com o uso do Git, assim, você desejará se familiarizar com ele se planeja contribuir.

Este artigo é destinado a usuários do Subversion de nível iniciante a intermediário. Ele requer um conhecimento de nível iniciante do Subversion e algum conhecimento geral sobre os VCSs. As informações aqui são principalmente para usuários de sistemas com base em UNIX® (Linux® e Mac OS X), com alguma coisa destinada aos usuários do Windows® .

A Parte 2 desta série discutirá usos mais avançados do Git: mesclando ramificações, gerando diffs e outras tarefas comuns.

Conceitos Básicos do Subversion e do Git

De agora em diante, abreviarei "Subversion" como "SVN" para não desgastar as teclas U, B, E, R, S, I e O.

git-svn

Você pode ter ouvido falar sobre o git-svn, uma ferramenta que permite que você use o Git com um repositório Subversion. Embora útil em algumas situações, ser pouco distribuído e usar um VCS centralizado, não é o mesmo que alternar para um VCS distribuído.

Portanto, para o que o SVN é bom? Você talvez já saiba disso, mas um VCS não está relacionado a arquivos; está relacionado a alterações. O SVN, em execução em um servidor central, inclui alterações em seu repositório de dados e pode fornecer a você uma captura instantânea após cada alteração. Essa captura instantânea possui um número revisão; o número de revisão é muito importante para o SVN e para as pessoas que o usam. Se sua alteração for realizada após a minha, você certamente terá um número de revisão mais alto.

O Git possui um objetivo semelhante—controlar alterações—mas não possui nenhum servidor centralizado. Esta diferença é crucial. Enquanto o SVN é centralizado, o Git é distribuído; portanto, o Git não consegue fornecer um número de revisão crescente, porque não há nenhuma "revisão mais recente". Ele ainda possui IDs de revisão exclusivos; eles simplesmente não são tão úteis sozinhos quanto os números de revisão do SVN.

Com o Git, a ação crucial não é mais a consolidação; é a mesclagem. Qualquer um pode clonar um repositório e consolidar o clone. O proprietário do repositório tem a opção de mesclar alterações de volta. Como alternativa, os desenvolvedores podem empurrar alterações de volta ao repositório. Explorarei apenas este último, o modelo de push autorizado.


mantendo um diretório sob o SVN

Vamos começar com um exemplo simples e comum: controlando o conteúdo de um diretório com o SVN. Precisarei de um servidor SVN e, obviamente, um diretório de arquivos, assim como uma conta nesse servidor com direitos de consolidação para pelo menos um caminho. Comece incluindo e consolidando o diretório:

Lista 1. Configurando um diretório sob SVN
% svn co http://svnserver/...some path here.../top
% cd top
% cp -r ~/my_directory .
% svn add my_directory
% svn commit -m 'added directory'

O que isso permite que você faça? Agora você pode obter a versão mais recente de qualquer arquivo consolidado sob este diretório, excluir arquivos, renomeá-los, criar novos arquivos ou diretórios, consolidar alterações em arquivos existentes e mais:

Lista 2. Operações básicas de arquivo sob SVN
# get latest
% svn up
# what's the status?
% svn st
# delete files
% svn delete
# rename files (really a delete + add that keeps history)
% svn rename
# make directory
% svn mkdir
# add file
% svn add
# commit changes (everything above, plus any content changes)
% svn commit

Não examinarei esses comandos em detalhes aqui, mas mantenha-os em mente. Para obter ajuda sobre qualquer um desses comandos, apenas digite svn help COMMAND, e o Subversion mostrará uma ajuda básica; consulte o manual para obter ajuda mais detalhada.


Mantendo um diretório sob o Git

Seguirei o mesmo caminho que no exemplo do SVN. Como antes, estou assumindo que você já possui um diretório cheio de dados.

Para o servidor remoto, usarei o serviço github.com gratuito, mas, claro, você pode configurar seu próprio servidor se desejar. O GitHub é uma forma fácil de brincar com um repositório Git remoto. Até o momento da elaboração deste documento, uma conta gratuita é limitada a 300 MB de dados e seu repositório deve ser público. Inscrevi como usuário "tzz" e criei um repositório público chamado "datatest"; fique a vontade para usá-lo. Forneço minha chave pública SSH; você deve gerar se você ainda não possui uma. Você também talvez deseje experimentar o servidor Gitorious ou o repo.or.cz. Você encontrará uma longa lista de serviços de hospedagem do Git no git.or.cz Wiki (consulte Recursos para um link).

Uma coisa boa sobre o GitHub é que ele é fácil de usar. Ele informa exatamente quais comandos são necessários para configurar o Git e inicializar o repositório. Abordaremos isso mais adiante.

Primeiro, é necessário instalar o Git, que é diferente em cada plataforma e, em seguida, inicializá-lo. A página de download do Git (consulte Recursos) lista uma série de opções, dependendo da plataforma. (No Mac OS X, usei o comando port install git-core , mas você precisa configurar o MacPorts primeiro. Há também um instalador independente do MacOS X Git com link a partir da página de download do Git; isso provavelmente funcionará melhor para a maioria das pessoas.)

Assim que tiver concluído a instalação, veja a seguir os comandos que usei para uma configuração básica (selecione seu próprio nome de usuário e endereço de e-mail, naturalmente):

Lista 3. Configuração básica do Git
% git config --global user.name "Ted Zlatanov"
% git config --global user.email "tzz@bu.edu"

Você já deve perceber uma diferença do SVN; lá, sua identidade de usuário era do lado do servidor e você era quem quer que o servidor dissesse que você fosse. No Git, você pode ser O Maravilhoso Macaco de Wittgenstein se desejar (eu resisti à tentação).

Em seguida, configuro os arquivos de dados e inicializo meu repositório com eles. (O GitHub também importará a partir de um repositório público do SVN, o que pode ser útil.)

Lista 4. Configuração de diretório e primeira consolidação
# grab some files
% cp -rp ~/.gdbinit gdbinit
% mkdir fortunes
% cp -rp ~/.fortunes.db fortunes/data.txt
# initialize
% git init
# "Initialized empty Git repository in /Users/tzz/datatest/.git/"
# add the file and the directory
% git add gdbinit fortunes
% git commit -m 'initializing'
#[master (root-commit) b238ddc] initializing
# 2 files changed, 2371 insertions(+), 0 deletions(-)
# create mode 100644 fortunes/data.txt
# create mode 100644 gdbinit

Na saída acima, o Git está nos informando sobre os modos de arquivos; 100644 refere-se à versão octal dos bits de permissão nesses arquivos. Não é necessário se preocupar com isso, mas as 2371 inserções são difíceis de entender. Ele alterou apenas dois arquivos, certo? Esse número, na realidade, refere-se ao número de linhas inseridas. Não incluímos nenhuma, claro.

Que tal colocarmos nossas novas alterações no servidor GitHub? Os documentos nos instruem como incluir um servidor remoto chamado "origin" (você pode usar qualquer nome). Devo mencionar aqui que, se você deseja aprender mais sobre qualquer comando do Git, por exemplo, git remote, você digitaria git remote --help ou git help remote. Isso é típico para ferramentas de linha de comandos, e o SVN faz algo bastante semelhante.

Lista 5. Coloque as alterações no repositório remoto
# remember the remote repository is called "datatest"?
% git remote add origin git@github.com:tzz/datatest.git
# push the changes
% git push origin master
#Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts.
#Counting objects: 5, done.
#Delta compression using 2 threads.
#Compressing objects: 100% (4/4), done.
#Writing objects: 100% (5/5), 29.88 KiB, done.
#Total 5 (delta 0), reused 0 (delta 0)
#To git@github.com:tzz/datatest.git
# * [new branch]      master -> master

O aviso é do OpenSSH, pois o github.com antes não era um host conhecido. Nada com o que se preocupar.

As mensagens do Git são, digamos, meticulosas. Diferentemente das mensagens do SVN, que são fáceis de compreender, o Git é escrito para mentats, por mentats. Se você for do universo Dune de Frank Herbert e estiver treinado como um computador humano, você provavelmente já escreveu sua própria versão do Git, simplesmente porque é possível. Para o restante de nós, a compactação delta e o número de encadeamentos usados por ele são simplesmente não muito relevantes (e eles nos causam muitas dores de cabeça).

O push foi realizado sobre SSH, mas você pode usar outros protocolos, tal como HTTP, HTTPS, rsync e file. Consulte git push --help.

A seguir temos a diferença crucial, mais importante e básica entre SVN e Git. A consolidação do SVN diz "coloque isso no servidor central". Até consolidar no SVN, suas alterações são de outro mundo. Com o Git, sua consolidação é local, e você possui um repositório local, não importando o que acontece no lado remoto. É possível reverter uma alteração, ramificação, consolidação na ramificação e assim por diante, sem qualquer interação com o servidor remoto. O push com o Git é, efetivamente, uma sincronização do estado de ser repositório com o servidor remoto.

Certo, então, finalmente, vamos ver o log do Git do que acabou de acontecer:

Lista 6. O log do Git
% git log
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    initializing

Apenas a consolidação está no log (observe o longo e aparentemente aleatório ID de consolidação comparado com o número de revisão do SVN). Não há nada mencionando a sincronização via git push.


Colaborando por meio do Git

Até então, estivemos usando o Git em substituição ao SVN. Claro, para torná-lo interessante, precisamos ter múltiplos usuários e conjuntos de alterações envolvidos. Farei o registro de saída do repositório para uma outra máquina (executando Ubuntu GNU/Linux, neste caso; você precisará instalar git-core e não git):

Lista 7. Configurando uma outra identidade do Git e registrando a saída do repositório
% git config --global user.name "The Other Ted"
% git config --global user.email "tzz@bu.edu"
% git clone git@github.com:tzz/datatest.git
#Initialized empty Git repository in /home/tzz/datatest/.git/
#Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts.
#remote: Counting objects: 5, done.
#remote: Compressing objects: 100% (4/4), done.
#Indexing 5 objects...
#remote: Total 5 (delta 0), reused 0 (delta 0)
# 100% (5/5) done
% ls datatest
#fortunes  gdbinit
% ls -a datatest/.git
# .  ..  branches  config  description  HEAD  hooks  index  info  logs  objects  refs
% ls -a datatest/.git/hooks
# .  ..  applypatch-msg  commit-msg  post-commit  post-receive post-update
#  pre-applypatch  pre-commit  pre-rebase  update

Novamente, observe o aviso do OpenSSH indicando que não realizamos nenhuma operação com o GitHub sobre SSH antes a partir desta máquina. O comando git clone é como um registro de saída do SVN mas, em vez de de obter a versão sintetizada do conteúdo (uma captura instantânea a partir de uma determinada revisão ou da revisão mais recente), você está obtendo todo o repositório.

Incluí o conteúdo do diretório datatest/.git e o subdiretório de ganchos sob ele para mostrar que você realmente obtém tudo. O Git, por padrão, não guarda nenhum segredo, diferentemente do SVN que, por padrão, mantém o repositório privado e permite acesso apenas às capturas instantâneas.

Eventualmente, se você deseja empregar algumas regras em seu repositório Git, seja em todas as consolidações ou em outros momentos, os ganchos são o local. Eles são shell scripts, como os ganchos SVN, e possuem a mesma convenção UNIX padrão de "retornar zero para êxito, qualquer outra coisa para falha". Não entrarei em mais detalhes sobre os ganchos aqui, mas se sua ambição é usar o Git em equipe, definitivamente você deverá estudá-los.

Certo, então "O Outro Ted" é brincalhão e deseja incluir um novo arquivo na ramificação principal (aproximadamente equivalente ao TRUNK do SVN) e também cria uma nova ramificação com algumas alterações no arquivo gdbinit.

Lista 8. Incluindo um arquivo e criando uma nova ramificação
# get a file to add...
% cp ~/bin/encode.pl .
% git add encode.pl
% git commit -m 'adding encode.pl'
#Created commit 6750342: adding encode.pl
# 1 files changed, 1 insertions(+), 0 deletions(-)
# create mode 100644 encode.pl
% git log
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    adding encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    initializing
% git branch empty-gdbinit
% git branch
#  empty-gdbinit
#* master
% git checkout empty-gdbinit
#Switched to branch "empty-gdbinit"
% git branch
#* empty-gdbinit
#  master
% git add gdbinit
% git commit -m 'empty gdbinit'
#Created commit 5512d0a: empty gdbinit
# 1 files changed, 0 insertions(+), 1005 deletions(-)
% git push
#updating 'refs/heads/master'
#  from b238ddca99ee582e1a184658405e2a825f0815da
#  to   675034202629e5497ed10b319a9ba42fc72b33e9
#Generating pack...
#Done counting 4 objects.
#Result has 3 objects.
#Deltifying 3 objects...
# 100% (3/3) done
#Writing 3 objects...
# 100% (3/3) done
#Total 3 (delta 0), reused 0 (delta 0)

Esse foi um longo exemplo e espero que não tenha dormido; se dormiu, espero que tenha sonhado com os repositórios do Git sincronizando em uma infinita valsa de conjuntos de alterações. (Oh, você terá esses sonhos, não se preocupe.)

Primeiro, incluí um arquivo (encode.pl, apenas uma linha) e o consolidei. Após a consolidação, o repositório remoto no GitHub não tinha nenhuma ideia de que fiz alterações. Então, criei uma nova ramificação chamada empty-gdbinit e passei a usá-la (eu poderia ter feito isso com git checkout -b empty-gdbinit também). Nessa ramificação, esvaziei o arquivo gdbinit e consolidei aquela alteração. Finalmente, coloquei no servidor remoto.

Se eu passar a usar para a ramificação principal, não verei o gdbinit vazio nos logs. Portanto, cada ramificação possui seu próprio log, o que faz sentido.

Lista 9. Consultando logs entre ramificações
# we are still in the empty-gdbinit branch
% git log
#commit 5512d0a4327416c499dcb5f72c3f4f6a257d209f
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    empty gdbinit
#
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    adding encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    initializing
% git checkout master
#Switched to branch "master"
% git log
#commit 675034202629e5497ed10b319a9ba42fc72b33e9
#Author: The Other Ted <tzz@bu.edu>
#Date:   ...commit date here...
#
#    adding encode.pl
#
#commit b238ddca99ee582e1a184658405e2a825f0815da
#Author: Ted Zlatanov <tzz@lifelogs.com>
#Date:   ...commit date here...
#
#    initializing

Quando realizei o push, o Git disse, "Ei, olhe isso, um novo arquivo chamado encode.pl" nos servidores do GitHub.

A interface da Web do GitHub agora exibirá o encode.pl. Mas ainda há apenas uma ramificação no GitHub. Por que a ramificação empty-gdbinit não foi sincronizada? É porque o Git não assume que você deseja realizar o push de ramificações e suas alterações por padrão. Por isso, você precisa realizar o push de tudo:

Lista 10. Realizando o push de tudo
% git push -a
#updating 'refs/heads/empty-gdbinit'
#  from 0000000000000000000000000000000000000000
#  to   5512d0a4327416c499dcb5f72c3f4f6a257d209f
#updating 'refs/remotes/origin/HEAD'
#  from 0000000000000000000000000000000000000000
#  to   b238ddca99ee582e1a184658405e2a825f0815da
#updating 'refs/remotes/origin/master'
#  from 0000000000000000000000000000000000000000
#  to   b238ddca99ee582e1a184658405e2a825f0815da
#Generating pack...
#Done counting 5 objects.
#Result has 3 objects.
#Deltifying 3 objects...
# 100% (3/3) done
#Writing 3 objects...
# 100% (3/3) done
#Total 3 (delta 1), reused 0 (delta 0)

Novamente, a interface mentat está aqui completamente. Mas podemos resolver as coisas, certo? Talvez não sejamos mentats, mas pelo menos temos o senso comum para perceber que 0000000000000000000000000000000000000000 é algum tipo de tag inicial especial. Também podemos perceber nos logs na Lista 9 que a tag 5512d0a4327416c499dcb5f72c3f4f6a257d209f é a última (e única) consolidação na ramificação empty-gdbinit . O restante também pode estar em aramaico para a maioria dos usuários; eles simplesmente não se importam. O GitHub mostrará agora a nova ramificação e as alterações nela.

Você pode usar git mv e git rm para gerenciar arquivos, renomeando e removendo-os, respectivamente.


Conclusão

Neste artigo, expliquei conceitos básicos do Git e usei o Git para manter um conteúdo de diretório simples sob o controle de versão, comparando o Git com o Subversion. Expliquei a ramificação usando um exemplo simples.

Na Parte 2, explorarei a mesclagem, geração de diffs e alguns outros comandos do Git. Recomendo a leitura do manual do Git de fácil compreensão ou, pelo menos, uma passada pelo tutorial. Tudo está disponível na página inicial do Git, portanto, gaste algum tempo explorando-a. (Consulte Recursos abaixo para obter os links.) A partir da perspectiva de um usuário SVN, você não precisa muito mais que isso.

Por outro lado, o Git é um DVCS bastante poderoso; aprender mais sobre seus recursos quase certamente o levará a usá-los para simplificar e melhorar seu fluxo de trabalho no VCS. Além disso, você pode até ter um ou dois sonhos com os repositórios Git.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

  • Envolva-se com a comunidade My developerWorks; com seu perfil pessoal e página inicial customizada, é possível padronizar o developerWorks para seus interesses e interagir com outros usuários do developerWorks.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Linux, Software livre
ArticleID=423279
ArticleTitle=Git para Usuários do Subversion, Parte 1: Introdução
publish-date=08042009