(M)  s i s t e m a   o p e r a c i o n a l   m a g n u x   l i n u x ~/ · documentação · suporte · sobre

 

--- CVS Rápido

Definições

Módulo - um conjunto de arquivos (e.g. fontes que compõem um programa, páginas HTML que compõem um site, etc.).

Repositório - lugar onde ficam guardadas os módulos sob controle do CVS. O acesso ao repositório é feito através do comando "cvs".

Checkout - ação de extrair do repositório um módulo para um diretório de trabalho para posterior uso/alteração dos arquivos que compõe o módulo.

Diretório de trabalho - diretório onde os arquivos de um módulo residem e que está sob controle do usuário que fez o checkout. É no diretório de trabalho que se edita, compila, etc., os arquivo do módulo. Terminadas as alterações pode-se abandonar todas as mudanças (basta simplesmente apagar o diretório de trabalho) ou efetuar um commit.

Commit - ação de atualizar um módulo no repositório a partir das alterações feitas em arquivo(s) de um diretório de trabalho. O commit só atualiza os arquivos do repositório que não tenha sido alterado por outros. Se alguma alteração tiver ocorrido, será necessário fazer um update antes.

Update - ação de atualizar os arquivos de um diretório de trabalho em relação ao conteúdo de um módulo do repositório. O update tráz do repositório todas as alteração feitas por outros commits desde o último checkout. Updates fazem automaticamente alterações nos arquivos contidos no diretório de trabalho, desde que estas não interfiram em mudanças locais. Quando as alterações (merge) não são possíveis (foram feitas na mesma posição em que se alterou um determinado arquivo no diretório de trabalho), há um conflito.

Conflito - situação em que um update tenta alterar um arquivo do diretório de trabalho para refletir alterações no repositório, mas falha porque alguma alteração foi feita no mesmo lugar de um arquivo do diretório de trabalho.

Revisão - número que indica a versão (revisão, nos termos do CVS) de um arquivo de um módulo. Exemplos: 1.2, 3.4, 1.2.3.4, 3.27.56.3

Tag - símbolo que correlaciona as revisões de todos os arquivos que compõem um módulo. Um módulo pode ter várias tags associadas, cada uma correlacionando as diversas revisões dos arquivos que compõem o módulo. Usa-se tags normalmente para se referenciar uma versão do módulo, i.e., um conjunto de revisões dos arquivos que compõe o módulo e que formam aquela versão.

Main trunk - linha principal de desenvolvimento de um módulo. O CVS permite que diversas linhas de desenvolvimento de um módulo existam ao mesmo tempo. O main trunk é sempre a linha principal e é um tipo especial de branch.

Branch - linha de desenvolvimento de um módulo. Alterações em um branch podem ser incorporadas a outros branches a qualquer momento.

O Repositório

O repositório é na verdade um diretório que o CVS usa para controlar seu banco de dados de arquivos, versões e modificações.

O CVS utiliza a variável de ambiente $CVSROOT para saber qual repositório acessar ao executar uma ação. Pode-se também especificar o repositório a ser usado através do parâmetro -d.

O comando CVS

O comando cvs é usado para efetuar operações no repositório. Tem a seguinte forma:

cvs [sw1] cmd [sw2] [pars]
[sw1] São switches genéricos que servem para todos os comandos do cvs. Um exemplo é o switch -d que pode ser usado para se especificar o repositório a ser usado.
cmd É o comando (ação) a ser executado. Exemplos: checkout, update.
[sw2] São switches específicos do comando.
[pars] São os parâmetros do comando.

Iniciando

Tendo-se em mãos um conjunto de arquivos que compõe um programa, pacote, etc., o primeiro passo para utilizar o CVS para controle de versões é importá-lo no repositório. Usa-se para isso o comando import.

~ $ cd meu-pacote-1.1
~/meu-pacote-1.1 $ cvs import -m "Meu pacote" meu-modulo EU V_1_1
Onde cvs é o comando de invocação do CVS, import é o comando do CVS a executar (no caso, importar os fontes no repositório), -m "Meu pacote" é o parâmetro para comando import (especifica a mensagem de log da operação -- sem este parâmetro o cvs abre o seu editor, especificado na variável $EDITOR, para você editar o comentário), meu-modulo é o nome do (novo) módulo, EU é a vendor tag -- não é muito útil, porém obrigatório e, finalmente, V-1_1 é a tag inicial a ser atribuida aos arquivos importados.

Obtendo Arquivos para Trabalhar

Para obter arquivos de um módulo do CVS usa-se o seguinte comando:
cvs checkout modulo

Com este comando o CVS irá criar um diretório de trabalho chamado modulo imediatamento abaixo do diretório atual e colocará os arquivos que compõem o módulo ali. O diretório criado será deu diretório de trabalho.

Abreviação de comandos

O comando checkout pode ser abreviado para co (e.g. cvs co modulo). Vários comandos do CVS admitem abreviações. Use o comando cvs --help-synonyms para ver todas as abreviações possíveis.

Liberando um diretório de trabalho

Um diretório de trabalho pode ser liberado com o comando
cvs release dir
Este comando checa se foi feita alguma alteração nos arquivos do diretório de trabalho e, se alguma tiver sido feita, lhe avisa.

O comando cvs release não apaga o diretório de trabalho. Para que ele o faça, use-o da seguint forma:

cvs release -d dir
O comando cvs release é opcional. Você pode eliminar um diretório de trabalho usando simplesmente o comando rm. No entanto, o cvs release registra a liberação do módulo no seu histórico e, por isso, seu uso é recomendado.

Note também que não é necessário eliminar o diretório de trabalho. Você pode mantê-lo indefinidamente (no entanto você vai precisar usar o comando update sempre que quiser que as alterações feitas no repositório sejam refletidas no diretório).

Atualizando o Repositório

Uma vez que se tenha terminado com os arquivos do diretório de trabalho, e se tenha efetuado mudanças que devam ser incorporadas à versão "oficial" do módulo no repositório, deve-se usar o comando:

cvs commit [arq|dir] ...

Este comando analiza os arquivos arq ou do diretório dir (ou todos os arquivos do diretório corrente, se nada tiver sido especificado) e compara com a versão atual do repositório. Caso nenhuma mudança local no arquivo tenha sido feita, ele é ignorado. Caso ele esteja diferente da versão do repositório, ele compara as revisões do arquivo. Se a revisão do arquivo local for a mesma da do repositório, o arquivo avança para a próxima revisão e é inserido no repositório como versão oficial.

Se a revisão atual do arquivo local for diferente da versão existente no repositório (porque alguém fez um commit de uma revisão mais nova do que a que você obteve no checkout), o CVS incorporará as mudanças do repositório no arquivo local, o avancará para a revisão do repositório e tentará o commit novamente.

Nem sempre o CVS consegue incorporar as alterações feitas no repositório nos arquivos do diretório de trabalho. Quando a alteração aconteceu em um mesmo lugar que foi feita uma alteração local, a incorporação automática não é possível. Veja "Conflitos" abaixo.

Atualizando o Diretório de Trabalho

O CVS não implementa esquema de locking de módulo (pelo menos por default). Assim, é possível que a versão de um módulo que você fez checkout a algum tempo esteja desatualizada porque alguém já fez um commit.

Para atualizar os arquivos do diretório de trabalho refletindo as últimas alterações do repositório usa-se o comando:

cvs update [arq|dir] ...

Pode-se especificar apenas alguns arquivos a atualizar ou alguns diretórios. Se nenhum parâmetro for usado, o comando atualiza todos os arquivos e diretórios do diretório de trabalho atual.

O parâmetro -n

O CVS entende o parâmetro -n como "não faça nada -- apenas 'finja'". Em outras palavras, ao perceber este parâmetro o CVS faz como se a operação fosse realmente executada mas na verdade nada é alterado, seja no diretório local, seja no repositório. Um uso útil para este parâmetro é com o comando update (e.g. cvs -n update) que mostra a situação dos arquivos do diretório de trabalho (i.e. quais foram alterados, quais estão diferentes no repositório, etc.), mas sem fazer de fato o
update.

Adicionando Arquivos

Quando você inclui um novo arquivo no seu diretório de trabalho ele não é levado automaticamente para o repositório do CVS. Para informar ao CVS sobre o novo arquivo usa-se o comando:
cvs add arquivo ...

Removendo Arquivos

Se um arquivo do módulo atual não é mais necessário, você deve informar o fato ao CVS. Não basta somente excluir o arquivo para que o CVS o retire do repositório. Para que o CVS entenda o que você quer você precisa primeiro remover o arquivo (obrigatório) e depois usar o comando:
cvs rm arquivo

Dicas

  • Se você mexeu em um arquivo, não gostou das alterações e quer tê-lo de volta, apague-o do seu diretório de trabalho e depois user cvs update arquivo.
  • Se você apagou um arquivo acidentalmente, o comando cvs update arquivo também pode ser usado para trazê-lo de volta (obviamente sem qualquer alteração que você tenha feito).
  • Se você usou o comando cvs rm arquivo e quer voltar atrás, use cvs add arquivo.

Arquivos Ignorados

Quando o CVS vai fazer o commit de um diretório, todos os arquivos contidos nele são examinados. Para qualquer arquivo que exista no diretório e que não exista no repositório o CVS vai reclamar. Ou use o comando cvs add para adicionar o arquivo ao módulo ou o remova antes do commit.

O CVS mantém uma lista de arquivos e wildcards que devem sempre ser ignorados se existirem no diretório de trabalho (obviamente ele só ignora se o arquivo não fizer parte do módulo). Arquivos do tipo *.o, *~, core, *.a, *.bak, etc., são sempre ignorados. Você pode definir uma lista adicional que o CVS deve ignorar. Para isso, crie no diretório de trabalho o arquivo .cvsignore e inclua nele linhas com a(s) especificação(ões) do(s) arquivo(s) a ignorar.

Note que o arquivo .cvsignore vai se tornar parte do módulo e por isso você deve usar o comando cvs add .cvsignore ao criá-lo.

Conflitos

Durante o commit e o update o CVS pode querer incorporar mudanças feitas no repositório em arquivos locais. Ele faz isso transparentemente e na maioria das vezes as mudanças são incorporadas com sucesso. No entanto, se há uma mudança local feita no mesmo lugar que outra registrada no repositório a incorporação não é feita (do contrário ele perderia as mudanças locais).

Toda vez que o CVS não consegue fazer a incorporação das mudanças há um conflito. Quando isso acontece, seu arquivo é copiado sem mudança alguma para outro com nome .#nome-original.revisão-original e o arquivo com nome original é mantido com as mudanças das duas versões, separadas com alguns marcadores.

Por exemplo, supondo que a revisão 1.3 do arquivo funcs.c tenha o seguinte trecho:

	if ( strcmp(foo, "bar") == 0 )
	{
		puts("zee");
		return 0;
	}
Você fez o checkout desta revisão e alterou o trecho para:
	if ( strcmp(foo, "bar") == 0 )
	{
		puts("moe");
		return 0;
	}
Enquanto isso alguém fez um commit com a seguinte mudança (ou seja, no repositório a revisão do arquivo agora é 1.4).
	if ( strcmp(foo, "bar") == 0 )
	{
		printf("foo = %s\n", bar);
		return 0;
	}
Quando você executar cvs update, o comando vai mostrar algo parecido com:
	$ cvs update
	(...)
	retrieving revision 1.3
	retrieving revision 1.4
	Merging differences between 1.3 and 1.4 info funcs.c
	rcsmerge warning: overlaps during merge
	cvs update: conflicts found in funcs.c
	C funcs.c
	$
Neste ponto seu arquivo funcs.c original (o que você alterou) foi renomeado para .#funcs.c.1.3. A versão do funcs.c agora contém o seguinte:
	if ( strcmp(foo, "bar") == 0 )
	{
	<<<<<< funcs.c
		puts("moe");
	======
		printf("foo = %s\n", bar);
	>>>>>> 1.4
		return 0;
	}
A partir desta situação, você pode editar o arquivo, resolver o conflito e efetuar o commit da mudança, sendo ela então oficializada no repositório com o arquivo avançando para a revisão 1.5.

Note que o CVS não vai aceitar trabalhar com o arquivo em questão até que você resolva o conflito (o teste é feito levando-se em conta a data do arquivo e se ele contém algum marcador de conflitos).

Tags

As revisões dos arquivos que compõem um módulo não têm relação entre sí. Pode-se ter um módulo cujo arquivos tenham as seguintes revisões:
	Makefile	2.1
	main.c		2.3
	funcs.c		2.5
	utils.c		2.0

Em essência, o número de revisão de um arquivo reflete sua evolução sozinho, independente de qualquer outro arquivo do módulo.

O CVS implementa o recurso de tags para correlacionar as diversas revisões dos arquivos que compõem um módulo. Assim, supondo que se aplique a tag "RELEASE1" ao módulo de exemplo dado acima, a qualquer momento no futuro (quando provavelmente as revisões não vão ser mais aquelas) vai ser possível obter aquele conjunto de revisões com o comando:

cvs checkout -r RELEASE1 modulo
Para se marcar as revisões atuais com uma tag usa se o comando:
cvs tag TAG [arq|dir]
Ou:
cvs rtag TAG modulo
Na primeira forma a tag é aplicada aos arquivo ou diretórios especificados (ou ao diretório corrente). A segunda forma aplica a tag no repositório, o que torna desnescessária a existência de um diretório de trabalho.

Branches

O CVS implementa branches de desenvolvimento, ou, em outras palavras, linhas de desenvolvimento paralelas do mesmo módulo.

Um exemplo de branch é a preparação para a nova versão de um programa enquanto a versão antiga demanda alterações. Ou seja, libera-se a versão 1.0 de um programa e o desenvolvimento continua no main trunk para se chegar à versão 2.0. Enquanto isso, problemas vão sendo identificados na versão 1.0, mas estes problemas não podem ser corrigidos no main trunk porque este é a preparação para a versão 2.0, que provavelmente contém material não terminado ou ainda com problemas, que não pode ser usado para se construir um programa.

Nota: os números de versão deste exemplo (e.g. 1.0, 2.0, etc.) não se referem a revisões de arquivos e não devem ser confundidas como tal. São simplesmente a forma usual de se numerar versões de programa atualmente. Pense nestes números como tags, não como revisões.

A solução é criar um branch a partir da versão 1.0. Este branch contém os arquivos usados para se construir a versão 1.0, sem as mudanças inseridas na preparação para a 2.0. Os arquivos do branch agora podem ser usados e os problemas corrigidos, possibilitando a liberação de versões 1.1, 1.2, etc. A qualquer momento as alterações deste branch podem ser incorporadas à versão de desenvolvimento da 2.0 ou isto pode ser atrasado até que esta última esteja pronta.

Revisões e Branches

Os números de revisões de um arquivo têm na verdade uma estrutura hierárquica que possibilitam a identificação de que branch de desenvolvimento ele se encontra.

Veja um exemplo possível de avanço das revisões e branches:

	1.1
	 |
	1.2 ----- 1.2.1.1	# inicio do branch 1.2.1
	 |	   |
	1.3	  1.2.1.2
	 |	   |
	1.4	  1.2.1.3
	 |	   |
	 +<--------+		# incorporado ao main trunk
	 |
	1.5 ----- 1.5.1.1	# branch 1.5.1
	 |	   |
	1.6	  1.5.1.2
	 |	   |      
	1.7	  1.5.1.3 ----- 1.5.1.3.1.1	# branch 1.5.1.3.1
	 |	   |		 |
	1.8	  1.5.1.4	1.5.1.3.1.2
	 |	   |		 |
	1.9	   +<------------+	# incorporado ao branch original
	 |	   |
	1.10	  1.5.1.5
	 |	   |
	 +<--------+		# incorporado ao main trunk
	 |
	1.11
	 |

Iniciando um Branch

Para iniciar um branch a partir de uma versão de módulo com tag TAG1, usa-se o seguinte comando:

cvs rtag -b -r TAG1 TAG1-BRANCH modulo
Isto cria o branch (-b) TAG1-BRANCH a partir das revisões do módulo com tag TAG1 (se -r não for usado o branch inicia do main trunk).

A partir deste ponto pode-se obter os arquivos do branch com o comando:

cvs co -r TAG1-BRANCH modulo

Juntando branches

Um branch pode ser juntado a outra branch usado o parâmetro -j com o comando update. Por exemplo, para juntar o branch 1.2.1 ao main trunk do exemplo anterior pode-se usar o comando (supondo que a tag V1_fix foi atribuida ao branch):
cvs update -j V1_fix

Numeros de Revisão

Os números de revisão de um arquivo são compostos de uma versão maior e uma menor (e.g. 1.2, 4.5, etc.). A versão menor é avançada automaticamente à medida em que o arquivo evolui -- ela é aumentada em 1 automaticamente a cada . A versão maior nunca é alterada implicitamente.

Para se fazer um commit para uma revisão especifica (maior do que a atual, obviamente), usa-se o comando:

cvs commit -r nova-rev
Exemplo:
	cvs commit -r 3.0
	# Faz o commit e inicia com revisão 3.0

Referências

O CVS é muito mais do que foi explicado acima. Os seguintes documentos (em inglês) oferecem uma visão mais completa deste sistema: