Modelo de controles

Todo sistema de controle de versão precisa resolver algumas problemas fundamentais: como o sistema vai permitir aos usuários compartilhar a informação, mas prevenindo que um não atrapalhe o outro? É muito fácil para os usuários acidentalmente sobreescrever as modificações de outros no repositório.

O problema do compartilhamento de arquivo

Considere o cenário: suponha que nós temos dois usuários, Harry e Sally. Cada um deles decide editar o mesmo arquivo no mesmo repositório ao mesmo tempo. Se Harry salvar suas alterações no repositório primeiro, é possível que (alguns tempo depois) Sally poderia acidentalmente sobreescrever as alterações com sua versão do arquivo. Enquanto a versão do arquivo do Harry se perderia para sempre (porque o sistema guarda cada modificação), qualquer alteração que Harry fez não estariam presentes na nova versão do arquivo de Sally, porque ela nunca viu as modificações do Harry. O trabalho do Harry foi perdido - ou no mínimo estaria na versão mais recente - e provavelmente por acidente. Esta é definitivamente um situação que nós queremos evitar!

Figura 2.2. O problema a ser evitado

O problema a ser evitado

A solução Alocar-Modificar-Desalocar

Muitos sistemas de controle de versão usam o modelo alocar-modificar-desalocar para resolver este problema, o qual é uma solução simples. Em cada sistema, o repositório permite somente uma pessoa por vez modificar o arquivo. Primeiro Harry deve alocar o arquivo antes que possa fazer as alterações. Alocar um arquivo é como um controle de biblioteca/ se Harry alocou o arquivo, então Sally não pode fazer qualquer alteração nele. Se ela tentar alocar o arquivo, o repositório vai negar essa solicitação. Tudo que ela pode fazer é ler o arquivo, e esperar até que Harry acabe as suas alterações e libere o arquivo. Depois que Harry desalocar o arquivo, sua vez acaba, e então é a vez de Sally alocar o arquivo e fazer suas alterações.

Figura 2.3. A solução Alocar-Modificar-Desalocar

A solução Alocar-Modificar-Desalocar

O problema com o modelo alocar-modificar-desalocar é que é muito restritivo, e muitas vezes é um empecilho para os usuários:

  • Alocação pode causar problemas administrativos. Algumas vezes Harry vai alocar o arquivo e então esquecer dele. Entretanto, porque Sally continua esperando para para editar o arquivo, suas mãos estão atadas. E então Harry sai de férias. Agora Sally precisa pedir a um administrador para liberar o arquivo alocado por Harry. A situação acaba causando atrasos e uma porção de tempo perdido desnecessário.

  • Alocação pode causa uma serialização desnecessária. O que fazer se Harry estava editando o início de um arquivo texto, e Sally quer editar apenas o fim do arquivo? Estas alterações não se sobrepoem. Eles poderiam facilmente editar o arquivo ao mesmo tempo, e nenhum grande problema ocorreria, assumindo que as modificações seriam corretamente unificadas. Não é necessário travar o arquivo neste caso.

  • Alocar pode criar uma falta noção de segurança. Suponhamos que Harry aloque e altere o arquivo A, enquanto ao mesmo tempo Sally aloca e edita o arquivo B. Supondo que A e B dependem um do outro, e que as modificações feitas em cada um são semanticamente incompatíveis. Imprevisivelmente A e B não funcionam mais juntos. O sistema de alocação não tem como prever este problema - ainda que esse sistema passe uma falta sensação de segurança. É fácil para Harry e Sally imaginar que alocando arquivos, cada um está seguro, numa tarefa isola, e deste modo evitando discussões precosss sobre as modificações.

A solução Copiar-Modificar-Unificar

Subversion, CVS, and other version control systems use a copy-modify-merge model as an alternative to locking. In this model, each user's client reads the repository and creates a personal working copy of the file or project. Users then work in parallel, modifying their private copies. Finally, the private copies are merged together into a new, final version. The version control system often assists with the merging, but ultimately a human being is responsible for making it happen correctly.

Aqui vai um exemplo. Digamos que Harry e Sally criam cada um uma cópia de trabalho de um mesmo projeto, copiado do repositório. Eles trabalham ao mesmo tempo, e fazem modificações em um mesmo arquivo A em suas cópias. Sally salva suas alterações no repositório primeiro. Quando Harry tenta salvar suas modificações após Sally, o repositório informa a ele que o arquivo A está desatualizado. Em outras palavras, o arquivo A do repositório tem alguma alteração desde a última vez que ele foi copiado. Então Harry é questionado sobre a unificação das modificações no repositório serem inseridas em sua cópia do arquivo A. Oportunamente as modicações de Sally não foram sobreescritas pelas dele; uma vez que ele unificou ambas as alterações, ele salva a sua cópia no repositório.

Figura 2.4. A solução Copiar-Modificar-Unificar

A solução Copiar-Modificar-Unificar

Figura 2.5. ...Continuando com Copiar-Modificar-Unificar

...Continuando com Copiar-Modificar-Unificar

Mas o que acontece se as alterações de Sally se sobrepoem sobre as alterações de Harry? O que então deve ser feito? Esta situação é chamada de conflito, e em geral isto não é um problema. Quando Harry for questionado sobre a unificação das últimas alterações no repositório em sua cópia de trabalho, sua cópia do arquivo A de qualquer maneira é marcada como conflitante: ele verá todas as modificações em conflito, e manualmente resolverá. Entenda que o software não pode resolver automaticamente os conflitos; somente humanos são capazes de entender quais são as escolhas lógicas a serem tomadas. Uma vez que Harry manualmente resolveu o que estava se sobreponde (talvez precise discutir o conflito com Sally!), ele pode seguramente salvar o arquivo unificado de volta no repositório.

O modelo copiar-modificar-unificar pode parecer bagunçado, mas na prática, isto funciona grandemente. Usuários podem trabalhar paralelamente, sem esperar por outros. Quando eles trabalham num mesmo arquivo, a maioria das alterações não se sobrepoem; conflitos são pouco frequentes. E na maioria das vezes o tempo que leva para resolver os conflitos é muito menor que o tempo perdido em um sistema de alocação.

No final das contas, tudo isso acaba em um ponto crítico: comunicação entre os usuários. Quando os usuários não se comunicam direito, aumenta-se os conflitos sintáticos e semênticos. Nenhum sistema pode forçar uma perfeita comunicação, nenhum sistema pode detectar conflitos de semântica. Então não há porque se entusiasmar com falsas promessas de que um sistema de alocação evitará conflitos; na prática, alocações parecem restringir a produtividade mais que qualquer outra cosa.

Existe uma situação em comum onde o modelo alocar-modificar-desalocar se torna melhor, e é com arquivos que não são unificáveis. Por exemplo, se seu repositório contém alguns arquivos de imagens, e duas pessoas mudam a imagem ao mesmo tempo, não há nenhuma maneira de combinar as alterações. Ou Harry ou Sally perderá sua alteração.

O que o Subversion faz?

Subversion usa a solução copiar-modificar-unificar como padrão, e na maioria dos casos é o suficiente. Contudo, a partir da versão 1.2, Subversion também permite alocar um arquivo, e se existem arquivos que não são unificáveis, você pode adotar uma política de alocação, que o Subversion está preparado para o que você precisa.