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:
- saber os conceitos básicos do controle de versão distribuído;
- instalar o Mercurial ou o TortoiseHg na sua máquina;
- 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:
- O arquivo numeros.txt está desatualizado em relação à última revisão do repositório. É necessário atualizar/mesclar para que seja aceito.
- 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 push e pull.
À 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.