# Sistema de controle de versões

Um sistema de controle de versões (ou versionamento), VCS (do inglês version control system) ou ainda SCM (do inglês source code management) na função prática da Ciência da Computação e da Engenharia de Software, é um software que tem a finalidade de gerenciar diferentes versões no desenvolvimento de um documento qualquer. Esses sistemas são comumente utilizados no desenvolvimento de software para controlar as diferentes versões — histórico e desenvolvimento — dos códigos-fontes e também da documentação.
Esse tipo de sistema é muito presente em empresas e instituições de tecnologia e desenvolvimento de software. É também muito comum no desenvolvimento de software livre. É útil, em diversos aspectos, tanto para projetos pessoais pequenos e simples como também para grandes projetos comerciais.
Entre os mais comuns encontram-se as soluções livres: CVS, Mercurial, Git e SVN (Subversion); e as comerciais: SourceSafe, TFS, PVCS (Serena) e ClearCase. O desenvolvimento de software livre utiliza mais o Git (com repositórios no GitHub), que vem substituindo o SVN, que por sua vez é um sucessor do CVS. Muitas empresas também adotam o Git (como a Microsoft com o código fonte do Windows) ou o SVN, embora algumas empresas prefiram uma solução comercial, optando pelo ClearCase (da IBM) ou Team Foundation Server (da Microsoft). Optar por uma solução comercial geralmente está relacionada à garantia, pois as soluções livres não se responsabilizam por erros no software e perdas de informações, Porém as soluções livres podem ter melhor desempenho e segurança que as comerciais. As soluções comerciais apesar de supostas garantias adicionais, não garantem o sucesso da implementação nem indenizam por qualquer tipo de erro mesmo que comprovadamente advindo do software.
A eficácia do controle de versão de software é comprovada por fazer parte das exigências para melhorias do processo de desenvolvimento de certificações tais como CMMI e SPICE.

## Principais vantagens

As principais vantagens de se utilizar um sistema de controle de versão para rastrear as alterações feitas durante o desenvolvimento de software ou o desenvolvimento de um documento de texto qualquer são:
* Controle do histórico: facilidade em desfazer e possibilidade de analisar o histórico do desenvolvimento, como também facilidade no resgate de versões mais antigas e estáveis. A maioria das implementações permitem analisar as alterações com detalhes, desde a primeira versão até a última.
* Trabalho em equipe: um sistema de controle de versão permite que diversas pessoas trabalhem sobre o mesmo conjunto de documentos ao mesmo tempo e minimiza o desgaste provocado por problemas com conflitos de edições. É possível que a implementação também tenha um controle sofisticado de acesso para cada usuário ou grupo de usuários.
* Marcação e resgate de versões estáveis: a maioria dos sistemas permite marcar onde é que o documento estava com uma versão estável, podendo ser facilmente resgatado no futuro.
* Ramificação de projeto: a maioria das implementações possibilita a divisão do projeto em várias linhas de desenvolvimento, que podem ser trabalhadas paralelamente, sem que uma interfira na outra.
* Segurança: Cada software de controle de versão usa mecanismos para evitar qualquer tipo de invasão de agentes infecciosos nos arquivos. Além do mais, somente usuários com permissão poderão mexer no código.
* Rastreabilidade: Com a necessidade de sabermos o local, o estado e a qualidade de um arquivo; o controle de versão traz todos esses requisitos de forma que o usuário possa se embasar do arquivo que deseja utilizar.
* Organização: Alguns softwares disponibilizam uma interface visual onde podem ser vistos todos os arquivos controlados, desde a origem até o projeto por completo.
* Confiança: O uso de repositórios remotos (na nuvem) ajuda a não perder arquivos por eventos inesperados. Além disso, e possível fazer novos projetos sem danificar o desenvolvimento do atual.

## Funcionamento básico

Cada implementação possui sua particularidade, mas a maioria deles compartilham alguns conceitos básicos. Nota: Apesar disso, é possível que algum sistema específico funcione de maneira totalmente diferente da explicada neste capítulo.
A maior parte das informações - com todo o histórico - ficam guardadas num repositório (repository em inglês), num servidor qualquer. Geralmente um cliente pode acessar o repositório pela rede ou localmente, quando o cliente está na mesma máquina do servidor.
O repositório armazena a informação - um conjunto de documentos - de modo persistente num sistema de arquivos ou num banco de dados qualquer - onde ocasiona um tipo de hierarquia entre arquivos e diretórios. Inúmeros clientes podem se conectar em um repositório, e assim leem e escrevem nesses arquivos. Incrementando dados, um usuário disponibiliza a informação para outros; fazendo a leitura dos elementos, um usuário recebe a informação de outros. Além disso, é possível armazenar o conteúdo em outros dispositivos capazes de "eternizar" e resgatar facilmente a informação.
Cada servidor pode ter vários sistemas de controle de versão e cada sistema pode ter diversos repositórios, limitando-se na capacidade de gerenciamento do software e também no limite físico do hardware. Geralmente um repositório possui um endereço lógico que permite a conexão do cliente. Esse endereço pode ser um conjunto IP/porta, uma URL, um caminho do sistema de arquivos, etc.
Cada desenvolvedor possui em sua máquina uma cópia local (também chamada de working copy em inglês) somente da última versão de cada documento. Essa cópia local geralmente é feita num sistema de arquivos simples (FAT, NTFS, ext3, etc). A cada alteração relevante do desenvolvedor é necessário "atualizar" as informações do servidor submetendo (commit em inglês) as alterações. O servidor então guarda a nova alteração junto de todo o histórico mais antigo. Se o desenvolvedor quer atualizar sua cópia local é necessário atualizar as informações locais, e para isso é necessário baixar novidades do servidor (ou fazer update em inglês).

### Envio e resgate de versões

A principal função do sistema de controle de versão é armazenar todo o histórico de desenvolvimento do documento, desde o primeiro envio até sua última versão. Isso permite que seja possível resgatar uma determinada versão de qualquer data mais antiga, evitando desperdício de tempo no desenvolvimento para desfazer alterações quando se toma algum rumo equivocado.
O envio das alterações é feito a gosto do desenvolvedor (do lado do cliente), quando ele desejar; mas, para minimizar conflitos de versões, facilitar no desfazer de alterações e também no controle do histórico, recomenda-se que uma alteração seja enviada a cada vez que o software estiver minimamente estável, i. e., a cada nova parte (uma função, e. g.) ou a cada alteração relevante que esteja funcionando corretamente. Não é recomendável o envio quando o documento como um todo possa causar alguma dificuldade no desenvolvimento de outro colaborador, como por exemplo um código não compilado ou com algum defeito que comprometa a execução geral.
Cada "envio" é na maioria dos sistemas chamado de "commit" (às vezes "submit"), ou seja, efetivar as alterações no (ou "submeter" ao) repositório. Cada envio produz uma nova versão no repositório e é armazenado como "uma fotografia" do momento.
| fig. c - Em sistemas no estilo do CVS, cada documento tem sua versão controlada individualmente. Assim, é necessário adicionar marcas ('tags' - em inglês) para que se tenha uma "fotografia" de determinado momento. Ou seja, o versionamento do conjunto fica a cargo do usuário pois a numeração gerada pelo sistema de controle de versão não fornece "alinhamento" aos documentos. | fig. d - Já em sistemas no estilo do SVN, o controle de versão é feito por cada envio ao servidor. Ou seja, há uma versão global para todos os documentos. Se você enviar 4 versões do arquivo B enquanto você enviou apenas 2 versões do A, ambos estão na versão final que é a 4. Perceba que toda "fotografia" de qualquer momento será sempre uma coluna alinhada como mostra a figura. |
Se o arquivo fosse armazenado diretamente num sistema de arquivos simples, não haveria histórico, a menos que isso fosse feito manualmente através de cópias completas dos documentos numa organização (que pode ou não envolver pastas) que dependerá do desenvolvedor.

### Histórico de envio

Muitas vezes, é possível acrescentar comentários no envio das alterações, o que facilita também uma possível análise do histórico. Geralmente o relatório com as versões e os comentários de cada envio são chamados de "histórico" ou "log", e uma análise deste relatório pode facilitar em muitos aspectos no desenvolvimento do produto.
A documentação do CVS, SVN e outros, recomendam que o comentário do histórico seja amplo, geral e abstrato, ou seja, que não se limite à explicação da mudança do código em si, mas sim sobre o que foi mudado ou acrescentado no conceito ou no funcionamento como um todo. A mudança do código pode ser analisada através de uma diferença (ou diff) entre duas versões, portanto o comentário seria útil apenas para explicar a mudança de forma lógica.
Exemplo prático dessa recomendação: utilize "acréscimo de uma condição que verifica se existe saldo na conta para não permitir que seja sacado sem saldo" ao invés de um comentário contendo o próprio código modificado como:
* "+ if (!this.haSaldoNaConta) { this.proibeSaque }"

### Trabalho em equipe

Sistemas de controle de versão também são convenientes quando diversos desenvolvedores trabalham sobre o mesmo projeto simultaneamente, resolvendo eventuais conflitos entre as alterações. A maioria dos sistemas possui diversos recursos como ramificação e mesclagem de histórico para auxiliar nessas tarefas.
Para que seja possível o trabalho em equipe, o sistema de controle de versão pode possuir um mini sistema de controle de usuários embutido ou pode utilizar algum outro sistema de autenticação separado. Assim, é possível identificar cada usuário, que geralmente fica protegido por uma senha pessoal, ou alguma senha criada pelo administrador de sistemas.
No CVS, por exemplo, é possível escolher o método de autenticação a ser usado, dentre várias opções. No caso do SVN, por exemplo, se ele estiver rodando via Apache, o controle de usuários poderá ser feito pela autenticação padrão do Apache. Embora menos comum, é possível também configurar o SVN para utilizar o usuário do sistema, como os usuários do Linux ou do Windows.

#### Mesclagens Otimistas vs Edições Exclusivas

Com relação ao trabalho em equipe num sistema de controle de versão, há basicamente dois métodos (ou filosofias) relevantes de edição:
* "Optimistic Merges" ("Mesclagens Otimistas") ou "Branch and Merge" ("Ramificando e Mesclando") ou ainda "Copia-modifica-resolve"
* "Exclusive Lock" ("Tranca exclusiva", "Edições exclusivas") ou ainda "Trava-modifica-destrava")
Nota: a ausência de um sistema de controle de versão, ou seja, o trabalho direto num sistema de arquivos comum é equivalente ao "Exclusive Lock" nesse aspecto. Há também alguns sistemas, como o MediaWiki (pelo menos até a versão 1.8) e. g., que permitem a edição simultânea (sem trancar ou bloquear o outro) mas que não gerenciam automaticamente os conflitos, tendo que ser feitos manualmente sempre.
A filosofia "Optimistic Merges" ("Mesclagens Otimistas"), é um método de conflitos otimista que é geralmente padrão na maioria dos sistemas abertos, como o SVN e CVS. Essa filosofia presume que os conflitos de edições são tão pequenos e pontuais — se houver relativa atualização frequente do repositório por ambos — que a grande maioria das fusões podem ser feitas de forma automática, restando para fusões manuais somente casos em que a alteração for feita num mesmo ponto de um mesmo arquivo. A prática demonstra que essa visão é, na verdade, também a mais realista. O capítulo #"Demonstração de Mesclagens Otimistas" demonstra como esse método funciona na prática.
Em contrapartida, numa visão mais pessimista (ou "conservadora"), pode-se afirmar que, se houver muitas modificações simultâneas sem intervalos pequenos de atualização mútua num mesmo arquivo, é possível que a fusão manual se torne tão complicada a ponto de desperdiçar parcialmente ou totalmente o trabalho de um ou de outro editor usuário do sistema. É por esse principal motivo que alguns sistemas, geralmente as soluções comerciais como o ClearCase e o SourceSafe, adotam outro método de trabalho como padrão: o "Exclusive Lock" ("Tranca exclusiva" ou "Edições exclusivas"). Esse método consiste basicamente em deixar apenas um usuário editar um arquivo de cada vez, sendo que este fica bloqueado enquanto não houver um reenvio (atualização) do editor ao servidor. É possível mesclagem neste método, mas apenas após a liberação (ou desbloqueio) do editor. O capítulo #"Edições Exclusivas" ou ausência de um sistema de controle de versão demonstra como esse método funciona na prática.

#### Demonstração de "Mesclagens Otimistas" passo-a-passo

A seguir, é demonstrado em alguns passos, numa edição fictícia, como funciona o método de "Mesclagens Otimistas". Cada animal personificado a seguir nas figuras - Pig, Dog e Panda - representam um programador independente (com ou sem comunicação entre si), que podem estar em locais físicos separados.

##### 6° e último passo: submetendo a versão final
#### "Edições Exclusivas" ou ausência de um sistema de controle de versão

No método mais conservador, ou quando se compartilha o mesmo projeto numa rede diretamente num sistema de arquivos simples, sem um sistema de controle de versão, alguns arquivos ficam bloqueados para escrita enquanto estão sendo utilizados. Ainda, um agravante na ausência do sistema de controle de versão, é que o fluxo de informações pela rede é alto porque a cada modificação substancial é necessário reenviar o documento todo e a chance de corromper arquivos também aumenta; o que não acontece com um sistema de controle de versão, pois cada desenvolvedor possui uma cópia local do projeto, trabalhando localmente, baixando as atualizações e enviando as alterações.

##### Mesclagem no método "Edições Exclusivas"

A mesclagem no método "Edições Exclusivas" é ainda possível desta forma:
* usuário A dá checkout (ou update).
* B tenta dar checkout e não consegue porque A está bloqueado.
* B dá checkout não reservado (sem bloquear).
* B tenta dar commit (ou checkin), mas não consegue, B fica aguardando A liberar o lock (bloqueio).
* A dá commit ou release, liberando a trava.
* B dá um update & merge (que já cria um lock para ele).
* B dá commit com a versão mesclada.

#### Bloqueio de arquivo

Alguns sistemas permitem o bloqueio voluntário de qualquer arquivo. Alguns sistemas que suportam são o CVS e SVN (a partir da versão 1.2.0), por exemplo.
A opção de bloquear um arquivo é muito útil nos seguintes casos:
* Quando há trabalho simultâneo num mesmo arquivo de difícil ou impossível mesclagem.
* Ao editar um arquivo binário (que não permite a mesclagem), como arquivos compactados, bibliotecas, imagens etc. Não é muito recomendável trabalhar com arquivos binários num sistema de arquivos, porém muitas vezes é útil deixar arquivos binários junto do código-fonte ou da documentação, principalmente em casos em que é difícil gerar esses arquivos, como imagens, algumas bibliotecas etc.
* Quando há muita dificuldade na comunicação entre os desenvolvedores e conflitos freqüentes que desperdiçam muito tempo manual de mesclagem.

### Comparação de versões

É possível, na grande maioria dos sistemas de controle de versão (e quando o tipo de arquivo permite isso), comparar (também chamado de diff ou diferença) quaisquer versões entre si, enviadas a qualquer tempo. Saber exatamente o que foi acrescentado, modificado ou excluído em qualquer ponto dos documentos. Isso permite que seja feito uma análise minuciosa das alterações desde a criação do projeto até seu estado atual.

### Conflitos

É chamado de conflito de edição a situação em que dois ou mais usuários modificam o mesmo documento no mesmo intervalo de tempo entre o envio de uma nova versão ao sistema. A chance de conflitos aumentam quando aumentam o número de usuários utilizando o mesmo conjunto de documentos. O envio de alterações muito grandes podem também aumentar a chance de conflito.

#### Mesclagem

A mesclagem (ou merge em inglês) consiste na aglutinação (ou fusão) automática de versões através da comparação entre elas, quando há um conflito de edições simples.
Quando um conflito é direto, ou seja, no mesmo ponto do mesmo documento e o sistema não conseguiu resolver o conflito, automaticamente a mesclagem pode ser feita manualmente. Algumas implementações como o MediaWiki (até a versão 1.8 pelo menos) não possuem o sistema de "mesclagem", sendo assim, quando há qualquer conflito, mesmo os mais simples, é necessário resolvê-lo manualmente como descreve a seção "Resolução manual de conflitos".

#### Resolução manual de conflitos

Quando dois ou mais desenvolvedores modificam uma mesma região em um mesmo documento, é necessário resolver o conflito "manualmente". O software de Cliente fará uma cópia de segurança da sua alteração para que não haja chance de perda e depois mostrará o local de conflito. O software geralmente mostra os conflitos na tela e o desenvolvedor escolhe qual versão manter. Geralmente quando acontece esse tipo de coisa é porque houve falha na organização de divisão do trabalho e provavelmente uma alteração semelhante foi produzida na mesma região.

### Ramificações e marcações

Num sistema moderno de controle de versões é possível quebrar a linha do desenvolvimento em mais de um caminho. Isso pode ser chamado de ramificação (ramo), braços ou em inglês branches. Isso é muito útil quando se conquista uma versão estável dos documentos (ou software) ou quando se quer fazer uma tentativa "não convencional" fora do ramo principal.

### Otimização de espaço e velocidade

Geralmente um sistema assim mantém armazenado apenas a primeira versão e as diferenças entre elas, até formar a última, com o principal objetivo de economizar espaço. É claro que também existem outras otimizações que guardam a versão final ou versões recentes para que algumas operações possam ser feitas de modo mais rápido (utilizando uma espécie de cache). É possível também, dependendo do sistema e da configuração, que seja compactado algumas partes do repositório muito antigas que não estão sendo utilizadas de modo a salvar espaço.
Os sistemas são otimizados para trabalhar com arquivos texto e muitas vezes não se dão muito bem com arquivos binários. Sistemas mais modernos trabalham melhor com esse segundo tipo de arquivo, mas ainda assim de forma pouco satisfatória: tanto pelo alto consumo de espaço quanto pela dificuldade de se fazer comparação entre uma versão e outra.
Sistemas como o CVS e o SVN recomendam que documentos textos que necessitam de estilos, formatações especiais, tabelas e figuras, tais como o arquivo DOC do Microsoft Word que são em binário, sejam gravados em algum formato texto como o Rich Text Format (RTF), HTML ou XML (com quebras de linha entre uma tag e outra) porque internamente ele guarda a informação em texto. Um texto desse tipo não fica tão otimizado quanto um texto simples, mas ainda assim fica melhor que um arquivo binário.

## Integração com outros softwares

Os sistemas de controle de versões mais flexíveis permitem que seja possível integrá-los a outros softwares. A integração mais comum é em IDE (ambientes de desenvolvimento) através de plugins. Alguns ambientes que suportam a integração de alguns sistemas são: IntelliJ IDEA, Eclipse, NetBeans e Visual Studio. O TortoiseSVN, o TortoiseCVS e o TortoiseHg, clientes do SVN, do CVS e do Mercurial, respectivamente, funcionam sobre o Windows Explorer.

## Vocabulário comum

* Atualização / Update - Atualiza na cópia local as novidades do Servidor, provavelmente as mudanças enviadas por outro desenvolvedor.
* Baixar / Check-out ou checkout - Quando não existe cópia local e é necessário baixar todo o projeto do servidor. Nesse processo é guardado algum tipo de meta-dados (geralmente em pasta oculta) junto dos arquivos baixados.
* Conflito / Conflict - É a alteração simultânea (entre um update e um commit) de um mesmo documento por usuários diferentes.
* Cópia local / Working copy ou working area - É geralmente uma pasta no sistema operacional do desenvolvedor (do lado Cliente) que mantém a cópia da última versão do projeto. É através da cópia local que o Cliente compara com a última versão do Servidor e sabe exatamente o que foi modificado.
* Efetivar ou submeter / Commit, submit ou check-in - Enviar as alterações da cópia local ao Servidor através do Cliente.
* Exportar / Export - Semelhante ao checkout, mas não cria meta-dados junto da informação baixada. Esse processo é utilizado para gerar uma versão "distribuível" e impede (por não conter os meta-dados) que o desenvolvimento seja feito sobre ele.
* Importar / Import - É o processo que envia uma árvore de diretórios ainda não controlada (sem meta-dados) para o repositório pela primeira vez.
* Marcação / Tag ou release - É dar um nome a um determinado "momento" do repositório, ou seja, é como uma "fotografia" de determinada data. Alguns sistemas, como o SVN, não diferenciam entre "marcação" e "ramificação", pois é possível tratar uma ramificação com o conceito ou finalidade de marcação.
* Mesclagem / Merge ou integration - Permite que mais de um utilizador modifique um mesmo documento ao mesmo tempo, comparando as diferenças, mesclando e mantendo as duas alterações (se possível). A mesclagem geralmente é feita localmente (lado Cliente) na atualização de um documento quando há uma versão no Servidor mais recente que a sua.
* Mesclagem inversa / Reverse integration - É quando um braço é mesclado à linha principal.
* Modificação, diferença ou mudança (Change ou diff.) - Representa a diferença entre uma versão e outra de um mesmo documento.
* Raiz, linha principal ou braço principal / Head, trunk, mainline - é o caminho de revisões que não se quebrou em um braço.
* Ramificação ou braço / Branch - Quando a linha de desenvolvimento precisa ser dividida em duas ou mais.
* Repositório / Repository - local no Sistema onde fica armazenado todas as versões, desde a primeira até a última. Cada sistema geralmente pode ter mais de um repositório.
* Resolução de conflito / Conflict resolve ou Solve - Quando os desenvolvedores precisam analisar o que entrou em conflito e escolher qual alteração fará parte da versão final.
* Revisão ou versão / Revision ou version - Representa um determinado "momento" (uma "fotografia") de um repositório ou documento.
* Travar / Lock - Em alguns sistemas é possível bloquear um arquivo e ninguém pode alterá-lo nesse momento. Isso é pouco usado e pouco recomendado pois impede o uso simultâneo do mesmo arquivo por mais de um desenvolvedor, mas pode ser bastante útil com arquivos binários e/ou difíceis ou impossíveis de serem mesclados.
* Última versão / last revision - é a última versão enviada ao sistema no braço principal.
* Versão atualizada / Up-to-date - É quando a versão local é idêntica à que está no servidor. Quando alguém submete um documento (que você também está trabalhando) antes de você, o sistema não permite que você envie a sua versão enquanto você não deixar sua versão local atualizada (up-to-date).
* Versão estável / Stable version - Chama-se de "versão estável" uma determinada versão do sistema que está compilando normalmente e não possui nenhuma anomalia grave.
* Versão instável / Unstable version - Chama-se de "versão instável" uma versão do sistema que não está compilando ou que possui alguma anomalia bastante visível e geralmente grave.

## Lista de sistemas de controle de versão

Segue uma lista dos mais conhecidos:

### Soluções comerciais

* Microsoft Visual SourceSafe (VSS) - produto da Microsoft para controle de versão, integrado a muitas IDEs da Microsoft.
* Rational ClearCase - produto da IBM para controle de versão.
* Borland StarTeam - produto da Borland para controle de versão e de equipe.
* PVCS - Produto campeão da Serena do Brasil, controle de versão, possui também produtos que tem incorporada esta funcionalidade como o Dimension CM.

### Soluções livres

* Concurrent Version System (CVS) - software livre clássico e bem testado.
* Subversion (SVN) - alternativa também livre e mais eficiente que o CVS. Muitas fundações não-governamentais sem fins lucrativos ligadas ao desenvolvimento de software internacionalmente reconhecidas como a Apache Foundation já adotaram o Subversion como padrão.
* Git - Software para controle de versão distribuído com foco na velocidade.
* MediaWiki - software livre que possui um sistema integrado de controle de versões. Sites com os projetos da Wikimedia, tal como a Wikipédia mantém o sistema MediaWiki para o controle das versões dos documentos. Esse sistema permite o trabalho simultâneo de milhares de voluntários.
* GNU CSSC
* Revision Control System (RCS)
* Bazaar
* Darcs
* Mercurial - SCM usado para gerenciar o código fonte do Python
* Monotone
* SVK
    Para uma lista completa com comparações visite Lista de sistemas de controle de versão.