Posts Tagged ‘tutorial’

Controle de versão distribuído é diferente, mas nem tanto

7 Comments »

Não há dúvidas de que o controle de versão distribuído (Distributed Version Control System – DVCS) veio não só pra ficar, mas também para tomar o lugar das ferramentas de controle de versão centralizado. As etapas têm sido as mesmas de quando apareceu o Subversion com a proposta de substituir o CVS: 1. desconfiança, 2. curiosidade, 3. interesse, 4. aceitação.

Quem está tendo o primeiro contato com o DVCS geralmente cai na fase 1 (desconfiança). Não conhece como funciona e, por isso, desconfia. Afinal, se funciona do jeito que está (mesmo que não muito bem), pra que mudar?

O pessoal da fase 2 (curiosidade) já leu algo a respeito e está intrigado com as vantagens que “dizem” que o DVCS tem. Mas ainda falta um empurrãozinho para pelo menos tentar experimentar um DVCS pra ver como é.

O objetivo deste artigo é apresentar um experimento simples e rápido mostrando que o modo de trabalho de um DVCS, especificamente o Mercurial, não muda tanto assim do usado no Subversion. Espera-se com isso, levar o leitor mais perto da fase 3: interesse.

O experimento simulará dois usuários trabalhando no mesmo projeto, executando algumas operações bem comuns e básicas de controle de versão através do Mercurial, comparando sempre com o mesmo passo feito pelo Subversion.

Para aproveitar melhor o experimento, é necessário:

  1. saber os conceitos básicos do controle de versão distribuído;
  2. instalar o Mercurial ou o TortoiseHg na sua máquina;
  3. já ter usado o Subversion e ter ele ou o TortoiseSvn instalado na máquina;

Observação: O experimento será apresentado com operações pela linha de comando por questão de espaço e comodidade. O experimento pode ser feito também através das interfaces gráficas TortoiseHg e TortoiseSVN, que possuem os mesmos comandos usados no roteiro.

1. Preparando os Repositórios

Quando se sabe que no DVCS cada desenvolvedor tem um repositório e que um repositório pode se conectar com qualquer outro, logo se imagina que o modelo distribuído é uma anarquia. Na verdade, qualquer desenvolvimento sem regras vira uma bagunça. No modelo distribuído, os repositórios podem ser arranjados em várias topologias e a topologia cliente-servidor é uma delas.

Vamos criar 3 repositórios: um oficial, um para um user 1, e outro para o user 2, sendo esses dois últimos para simular os dois desenvolvedores. A convenção estabelece que não haverá comunicação direta entre o repositório dos desenvolvedores 1 e 2. Apenas através do repositório oficial, exatamente como acontece no modelo centralizado.

O acesso ao repositório oficial, tanto do Mercurial, quanto do Subversion, será feito por acesso local para manter o roteiro simples. No exemplo, será usado o diretório /tmp (que é o diretório temporário do linux) para manter todos os repositórios. Escolha um diretório que melhor lhe convier.

Mercurial Subversion
hg init /tmp/oficial svnadmin create /tmp/oficial
hg clone /tmp/oficial /tmp/user1
hg clone /tmp/oficial /tmp/user2
svn checkout file:///tmp/oficial /tmp/user1
svn checkout file:///tmp/oficial /tmp/user2

2. Publicação Inicial

O próximo passo é fazer uma primeira publicação no repositório. Use um arquivo chamado numeros.txt que deverá ser criado no diretório do repositório/cópia de trabalho com o seguinte conteúdo:

um
dois
três
Mercurial Subversion
user1 hg add numeros.txt svn add numeros.txt
hg status svn status
hg commit -m “primeiro commit” -u user1 svn commit -m “primeiro commit” –username user1
hg push

O Mercurial teve um passo adicional para enviar ao repositório oficial o que foi feito no repositório local.

3. Vendo o histórico do projeto?

Mercurial Subversion
user1 # é necessário atualizar a cópia de trabalho antes para ficar na última revisão
svn update
hg log

changeset: 0:aa3f592139e5
tag: tip
user: user1
date: Sun Apr 18 15:31:40 2010 -0300
summary: primeiro commit

svn log

—————————————————————
r1 | user1 | 2010-04-18 15:30:13 -0300 (Dom, 18 Abr 2010) | 1 line
primeiro commit
—————————————————————

Note que o Mercurial também fornece uma numeração sequencial além da identificação da revisão por hash. Esta numeração é válida apenas para o repositório local e foi criada por comodidade, para facilitar a referência a uma revisão em comandos locais, ao invés de se usar o identificador hash.

4. Atualização do Repositório do Usuário 2

O usuário 2 está com seu repositório desatualizado em relação ao repositório oficial. A sincronização se dá pelo comando hg pull -u que já atualiza a área de trabalho acoplada com a última revisão.

Mercurial Subversion
user2 hg pull -u svn update

5. Edição Concorrente

Usuários 1 e 2 executarão mudanças concorrentes no mesmo arquivo. user 1 acrescentará a palavra “zero” na primeira linha enquanto usuário 2 acrescentará “quatro” na última linha. Como as mudanças acontecerão em partes diferentes do mesmo arquivo, a mesclagem ocorrerá sem conflitos.

Mercurial Subversion
user1 # edita números.txt # edita números.txt
hg diff svn diff
hg commit -m “zero” -u user1 svn commit -m “zero” –username user1
hg push
user2 # edita números.txt # edita números.txt
hg diff svn diff
hg commit -m “quatro” -u user2 svn commit -m “quatro” –username user2
# falha 1. Veja obs.
hg push
# falha 2. Veja obs.
hg pull
hg merge
svn update
hg commit -m “merge” -u user1 svn commit -m “quatro” –username user2
hg push

Descrição das falhas nas operações:

  1. O arquivo numeros.txt está desatualizado em relação à última revisão do repositório. É necessário atualizar/mesclar para que seja aceito.
  2. Por padrão, a operação de push não permite que um ramo fique com mais de uma ponta, isto é, tenha bifurcações após a combinação dos grafos de revisões. Qualquer linha individual de desenvolvimento deve ser antes unificada localmente com a linha presente no repositório-oficial antes de ser enviada.

6. Visualização do Grafo de Revisões

O histórico de revisões do DVCS é um grafo acíclico direcionado (Directed Acyclic Graph – DAG). Na interface gráfica, é possível ver os caminhos sendo bifurcados e reunificados. Pela linha de comando, é necessário antes habilitar o plugin do Mercurial que conseguir ver o grafo textualmente.

Edite o arquivo de configuração do repositório do usuário 2, cujo caminho é /tmp/user2/.hg/hgrc e adicione as seguintes linhas ao final

[extensions]
hgext.graphlog =
Mercurial Subversion
user2 hg glog svn log
@ changeset: 3:3eddeb3252ea
|\ tag: tip
| | parent: 1:f01fe74e7279
| | parent: 2:c3664eb01670
| | user: user2
| | date: Sun Apr 18 22:06:03 2010 -0300
| | summary: merge
| |
| o changeset: 2:c3664eb01670
| | parent: 0:b353a0bdea31
| | user: user2
| | date: Sun Apr 18 22:05:21 2010 -0300
| | summary: quatro
| |
o | changeset: 1:f01fe74e7279
|/ user: user1
| date: Sun Apr 18 22:05:43 2010 -0300
| summary: zero
|
o changeset: 0:b353a0bdea31
user: user1
date: Sun Apr 18 22:04:40 2010 -0300
summary: primeiro commit

O grafo apresentado mostra que as revisões produzidas pelos usuários 1 e 2 formaram linhas independentes de desenvolvimento que depois foram reunificadas.

Conclusões

Usando o Mercurial na topologia cliente-servidor, com um repositório oficial equivalente ao repositório central do Subversion, nota-se que não há nenhuma grande mudança na forma do trabalho, nem nos comandos, que são idênticos para a maioria das operações. A impressão que se tem é de que o Mercurial é um Subversion com pushpull.

À primeira vista, parece que o Mercurial precisa de mais comandos para fazer a mesma coisa que se faz no Subversion. A razão disso, e que só é mostrado quando se vê o grafo de revisões, é que cada desenvolvedor trabalha em uma linha independente, equivalente a um ramo privativo, no qual pode publicar suas revisões sem a obrigatoriedade de mesclar com outra revisão a cada etapa, que é o que acontece no Subversion. O resultado é um fluxo de trabalho ainda melhor que no modelo centralizado.

No Mercurial, e em DVCS em geral, todo desenvolvedor trabalha naturalmente em um ramo privativo. O mesmo resultado poderia ser obtido no Subversion definindo-se ramos privativos para cada desenvolvedor a cada tarefa, bug etc. a ser implementado. Quem já usou ou tentou usar uma solução assim no Subversion, sabe quanto é trabalhoso e complicado fazer isso.