Felizmente para aqueles de nós que ainda são forçados a usar o CVS, o git fornece ferramentas muito boas para fazer exatamente o que você deseja. Minhas sugestões (e o que fazemos aqui no $ work):
Criando o Clone Inicial
Use git cvsimport
para clonar o histórico de revisão do CVS em um repositório git. Eu uso a seguinte invocação:
% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
-A /path/to/authors/file cvs_module_to_checkout
A -A
opção é opcional, mas ajuda a fazer seu histórico de revisão que é importado do CVS parecer mais com o git (veja man git-cvsimport
para mais informações sobre como isso é configurado).
Dependendo do tamanho e do histórico do repositório CVS, esta primeira importação levará MUITO tempo. Você pode adicionar um -v ao comando acima se quiser tranquilidade de que algo está de fato acontecendo.
Uma vez que este processo for completado, você terá um master
branch que deve refletir o HEAD do CVS (com a exceção que git cvsimport
por padrão ignora os últimos 10 minutos de commits para evitar pegar um commit que está pela metade). Você pode então usar git log
e amigos para examinar todo o histórico do repositório, como se ele estivesse usando o git desde o início.
Ajustes de configuração
Existem alguns ajustes de configuração que tornarão as importações incrementais do CVS (bem como as exportações) mais fáceis no futuro. Eles não estão documentados na git cvsimport
página do manual, então suponho que possam ser alterados sem aviso prévio, mas FWIW:
% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT
Todas essas opções podem ser especificadas na linha de comando para que você possa pular esta etapa com segurança.
Importações Incrementais
O subseqüente git cvsimport
deve ser muito mais rápido do que a primeira chamada. No entanto, ele faz um cvs rlog
em cada diretório (mesmo aqueles que têm apenas arquivos Attic
), portanto, ainda pode levar alguns minutos. Se você especificou as configurações sugeridas acima, tudo que você precisa fazer é executar:
% git cvsimport
Se você não definiu suas configurações para especificar os padrões, você precisará especificá-los na linha de comando:
% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout
De qualquer forma, duas coisas devem ser lembradas:
- Certifique-se de estar no diretório raiz do seu repositório git. Se você estiver em qualquer outro lugar, ele tentará fazer um novo
cvsimport
que levará uma eternidade.
- Certifique-se de estar em seu
master
branch para que as mudanças possam ser mescladas (ou rebased) em seus branches locais / tópicos.
Fazendo Mudanças Locais
Na prática, eu recomendo sempre fazer mudanças nos branches e apenas mesclar master
quando você estiver pronto para exportar essas mudanças de volta para o repositório CVS. Você pode usar qualquer fluxo de trabalho que desejar em seus branches (mesclagem, rebase, esmagamento, etc), mas é claro que as regras de rebase padrão se aplicam: não faça rebase se alguém mais estiver baseando suas alterações em seu branch.
Exportando alterações para CVS
O git cvsexportcommit
comando permite exportar um único commit para o servidor CVS. Você pode especificar um único ID de confirmação (ou qualquer coisa que descreva uma confirmação específica conforme definido em man git-rev-parse
). Um diff é então gerado, aplicado a um checkout do CVS e então (opcionalmente) comprometido com o CVS usando o cvs
cliente real . Você poderia exportar cada micro commit em seus branches de tópico, mas geralmente eu gosto de criar um merge commit em um up-to-date master
e exportar aquele único merge commit para CVS. Quando você exporta um commit de mesclagem, você tem que dizer ao git qual commit pai usar para gerar o diff. Além disso, isso não funcionará se sua mesclagem for um avanço rápido (consulte a seção "COMO FUNCIONA A man git-merge
mesclagem " de para uma descrição de uma mesclagem de avanço rápido), então você deve usar o--no-ff
opção ao realizar a fusão. Aqui está um exemplo:
# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD
Você pode ver o que cada uma dessas opções significa na página de manual de git-cvsexportcommit . Você tem a opção de definir a -w
opção em sua configuração git:
% git config cvsexportcommit.cvsdir /path/to/cvs/checkout
Se o patch falhar por qualquer razão, minha experiência é que você (infelizmente) provavelmente ficará melhor copiando os arquivos alterados manualmente e fazendo commit usando o cliente cvs. Isso não deve acontecer, no entanto, se você se certificar de que master
está atualizado com o CVS antes de mesclar seu branch de tópico no.
Se o commit falhar por qualquer motivo (problemas de rede / permissões, etc), você pode pegar o comando impresso em seu terminal no final da saída de erro e executá-lo em seu diretório de trabalho CVS. Geralmente é algo assim:
% cvs commit -F .msg file1 file2 file3 etc
Na próxima vez que você fizer um git cvsimport
(aguardando pelo menos 10 minutos), deverá ver o patch de seu commit exportado reimportado para seu repositório local. Eles terão IDs de commit diferentes, já que o commit do CVS terá um timestamp diferente e possivelmente um nome de committer diferente (dependendo se você configurou um arquivo de autor na inicial cvsimport
acima).
Clonando seu clone CVS
Se você tiver mais de uma pessoa precisando fazer o cvsimport
, seria mais eficiente ter um único repositório git que execute o cvsimport e ter todos os outros repositórios criados como um clone. Isso funciona perfeitamente e o repositório clonado pode executar cvsexportcommits conforme descrito acima. Há, no entanto, uma ressalva. Devido à maneira como os commits do CVS voltam com diferentes IDs de commit (como descrito acima), você não quer que seu branch clonado rastreie o repositório git central. Por padrão, é assim que git clone
configura seu repositório, mas isso é facilmente corrigido:
% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge
Depois de remover essas configurações, você terá que dizer explicitamente de onde e do que puxar quando quiser obter novos commits do repositório central:
% git pull origin master
No geral, descobri que esse fluxo de trabalho é bastante gerenciável e a "próxima melhor coisa" quando migrar completamente para o git não é prático.