Pular para o conteúdo principal

Conceitos Básicos de Controle de Versão de Software — Centralizado e Distribuído

Muitos problemas de desenvolvimento de software são causados por falta de controle de versão. Faça uma avaliação rápida da situação da sua equipe de desenvolvimento:

  1. Alguém já sobrescreveu o código de outra pessoa por acidente e acabou perdendo as alterações?
  2. Tem dificuldades em saber quais as alterações efetuadas em um programa, quando foram feitas e quem fez?
  3. Tem dificuldade em recuperar o código de uma versão anterior que está em produção?
  4. Tem problemas em manter variações do sistema ao mesmo tempo?

Se alguma das perguntas acima teve um sim como resposta, então sua equipe necessita urgentemente de um sistema para controle de versão! Não há mais desculpa para não usar uma ferramenta assim porque há várias opções open source disponíveis.

Há dois tipos de controle de versão: centralizado (Subversion) e distribuído (Mercurial e o Git).

Este artigo pretende responder a algumas perguntas relacionadas com controle de versão e ajudar sua empresa a se informar melhor e decidir baseada nas necessidades reais.

  1. Para que serve um sistema de controle de versão?
  2. Como funciona o controle de versão?
  3. Quais as semelhanças e diferenças entre o centralizado e o distribuído?

Para que Serve o Controle de Versão?

O Controle de versão apoia o desenvolvimento de diversas maneiras:

  • Registro do Histórico. Registra toda a evolução do projeto, cada alteração sobre cada arquivo. Com essas informações sabe-se quem fez o que, quando e onde. Além disso, permite reconstruir uma revisão específica do arquivo sempre que desejado;
  • Colaboração Concorrente. O controle de versão possibilita que vários desenvolvedores trabalhem em paralelo sobre os mesmos arquivos sem que um sobrescreva o código de outro, o que traria reaparecimento de defeitos e perda de funcionalidades;
  • Variações no Projeto. Mantém linhas diferentes de evolução do mesmo projeto. Por exemplo, mantendo uma versão 1.0 enquanto a equipe prepara uma versão 2.0.

Enfim, controle de versão é fundamental para o desenvolvimento de software. Todos os ambientes de desenvolvimento modernos, tais como o Visual Studio, Eclipse e o NetBeans, já possuem plugins para integração com algum sistema de controle de versão.

Como Funciona o Controle de Versão?

O controle de versão é composto de duas partes: o repositório e a área de trabalho. O repositório armazena todo o histórico de evolução do projeto, registrando toda e qualquer alteração feita em cada item versionado.

O desenvolvedor não trabalha diretamente nos arquivos do repositório. Ao invés disso, usa uma área de trabalho que contém a cópia dos arquivos do projeto e que é monitorada para identificar as mudanças realizadas. Essa área é individual e isolada das demais áreas de trabalho.

repositório e área de trabalho

Estrutura de um controle de versão é composta por repositório e área de trabalho. A comunicação entre elas se dá através de operações de commit e update.

A sincronização entre a área de trabalho e o repositório é feita através dos comandos commit e update. O commit envia um pacote contendo uma ou mais modificações feitas na área de trabalho (origem) ao repositório (destino). O update faz o inverso, isto é, envia as modificações contidas no repositório (origem) para a área de trabalho (destino).

Cada commit gera uma nova revisão no repositório, contendo as modificações feitas, data e autor. Uma revisão funciona como uma "foto" de todos os arquivos e diretórios em um determinado momento da evolução do projeto. As "fotos" antigas são mantidas e podem ser recuperadas e analisadas sempre que desejado. O conjunto dessas revisões é justamente o histórico do projeto.

Tanto o controle de versão centralizado quanto o distribuído possuem repositórios e áreas de trabalho. A diferença está em como cada uma dessas partes está arranjada.

Controle de Versão Centralizado

O controle de versão centralizado segue a topologia em estrela, havendo apenas um único repositório central mas várias cópias de trabalho, uma para cada desenvolvedor. A comunicação entre uma área de trabalho e outra passa obrigatoriamente pelo repositório central.

Topologia estrela

No controle de versão centralizado há um único repositório e várias cópias de trabalho que se comunicam apenas através do repositório central.

Controle de Versão Distribuído

São vários repositórios autônomos e independentes, um para cada desenvolvedor. Cada repositório possui uma área de trabalho acoplada e as operações commit e update acontecem localmente entre os dois.

Repositório acoplado com área de trabalho

No controle de versão distribuído cada desenvolvedor possui um repositório próprio acoplado a uma área de trabalho. A comunicação entre eles continua sendo através de commit e update.

Um repositório pode se comunicar com qualquer outro através das operações básicas pull e push:

  • pull (Puxar). Atualiza o repositório local (destino) com todas as alterações feitas em outro repositório (origem).
  • push (Empurrar). Envia as alterações do repositório local (origem) para um outro repositório (destino).

comunicação entre repositórios

Um repositório recebe e envia revisões com qualquer outro através de operações pull e push sem a necessidade de uma topologia pré-definida.

A sincronização entre os desenvolvedores acontece de repositório a repositório e não existe, em princípio, um repositório mais importante que o outro, embora o papel de um repositório central possa ser usado para convencionar o fluxo de trabalho.

Resumo das Operações Básicas dos Controles de Versão Centralizado e Distribuído

Centralizado Distribuído Descrição
checkout clone criação da cópia de trabalho/repositório
commit commit envia alterações para o repositório, criando uma revisão
update update atualiza a cópia/área de trabalho em uma revisão
pull importa revisões feita em outro repositório
push envia revisões locais para outro repositório

Identificação de Revisões

Uma revisão precisa de uma identificação única. No controle de versão centralizado, cada revisão produzida recebe um número inteiro sequencial: 1, 2, 3... Como só existe um repositório, a numeração de revisão é a mesma para todos os desenvolvedores.

image6

No sistema distribuído, os repositórios são autônomos e portanto não há como definir uma numeração sequencial compartilhada para todos. A solução é identificar cada revisão com uma numeração que nunca se repita em qualquer outro repositório.

A forma mais usada é através de um hash SHA-1, que produz um número de 160 bits (40 dígitos na forma hexadecimal). Esse um número é tão grande e específico que torna extremamente improvável a colisão com um hash produzido por outro repositório.

image7

Sincronização de Mudanças Concorrentes

Uma das responsabilidades do controle de versão é possibilitar o trabalho paralelo e concorrente de vários desenvolvedores sobre os mesmos arquivos, evitando que um sobrescreva o código de outro, o que resultaria no reaparecimento de defeitos e perda de funcionalidades.

Em parte, isto é conseguido através da área de trabalho, que fornece a impressão de que o desenvolvedor é o único dono de todo o projeto. Mas só a área de trabalho não resolve todo o problema. Ainda é necessário um jeito de sincronizar os esforços dos membros da equipe.

A sincronização é feita combinando-se revisões concorrentes em uma única resultante. Essa operação é conhecida como merge (mesclagem) e, apesar de parecer complexa, acontece sem conflitos na maioria das vezes — aliás, essa é a ideia.

As seções a seguir mostrarão como acontece a sincronização do trabalho de dois desenvolvedores nos controles de versão centralizado e distribuído.

Sincronização no Controle de Versão Centralizado

image8

  1. Duas cópias de trabalho são criadas a partir do comando checkout. As duas iniciam no mesmo estado.

image9

  1. Os dois desenvolvedores executam modificações nas suas cópias de trabalho, mas Aline publica antes no repositório.

image10

  1. Roberto tenta publicar suas alterações, mas o controle de versão recusa justificando que as alterações foram baseadas em arquivos desatualizados. No caso, um ou mais arquivos alterados por Roberto já haviam sido alterados por Aline antes.

image11

  1. Na atualização da cópia de trabalho, o controle de versão já mescla automaticamente as revisões.

image12

  1. Após conferir se a atualização e a mesclagem produziram o resultado desejado, Roberto envia as mudanças ao repositório. Enquanto isso, Aline já trabalha em outra tarefa, executando novas alterações.

image13

  1. O commit de Aline pode ser aceito sem problema se nenhuma das revisões que vieram depois da atualização da cópia de trabalho tiver alterado os mesmos arquivos que Aline. É uma situação possível de acontecer, mesmo que não seja comum.

Sincronização no Controle de Versão Distribuído

image14

  1. Roberto clona o repositório de Aline. Agora, ambos partem do mesmo ponto.

image15

  1. Aline e Roberto publicam suas alterações nos seus respectivos repositórios, sem interferir no repositório um do outro.

image16

  1. Roberto sincroniza seu repositório com as revisões publicadas por Aline. Sua área de trabalho não é afetada pela sincronização.

image17

  1. A mesclagem entre as revisões de Aline e Roberto é feita explicitamente na área de trabalho de Roberto através de um comando merge. Enquanto isso, Aline já gera outra revisão no seu repositório.

image18

  1. Após conferir se a mesclagem produziram o resultado desejado, Roberto envia as mudanças ao seu repositório. Paralelamente, Aline publica mais uma vez no seu repositório.

image19

  1. Roberto envia suas revisões ao repositório de Aline, que as combina com o histórico de revisões já existente.

Diferentes versões de projeto

Muitos projetos precisam de variações específicas. Um caso típico é para customizações feitas para atender determinados clientes que precisam de adaptações particulares. Outro caso comum é a criação de um ramo para experimentações no projeto, sem comprometer a linha principal de desenvolvimento.

Ramificações do Projeto

O controle de versão oferece funcionalidades que facilitam a coordenação de ramos diferentes de desenvolvimento em um mesmo projeto.

Considerações Finais

Controle de versão resolve diversos problemas intrínsecos ao desenvolvimento de software. É uma prática de engenharia de software comprovadamente eficaz. Por isso, faz parte das exigências para melhorias do processo de desenvolvimento de certificações tais como CMMi, MPS-Br e SPICE.

Existem várias ferramentas disponíveis para controle de versão. Para o controle de versão centralizado, recomendamos o Subversion. Para quem deseja usar o controle de versão distribuído, sugerimos o Mercurial ou o Git.

Comentários

Comments powered by Disqus