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 |
svn log
————————————————————— |
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.
