Comment exporter l'historique des révisions de mercurial ou git vers cvs?

100

Je vais travailler avec d'autres personnes sur le code d'un projet qui utilise cvs. Nous voulons utiliser un vcs distribué pour faire notre travail et quand nous avons terminé ou peut-être de temps en temps, nous voulons valider notre code et tout notre historique de révision dans cvs. Nous n'avons pas d'accès en écriture au dépôt cvs du projet, nous ne pouvons donc pas nous engager très fréquemment. Quel outil pouvons-nous utiliser pour exporter notre historique de révision vers des cvs? Actuellement, nous pensions utiliser git ou mercurial mais nous pourrions utiliser un autre vcs distribué si cela pouvait faciliter l'exportation.

tatsuhirosatou
la source
Quand vous dites «CVS distribué», je pense que vous voulez dire «VCS distribué» ou «DVCS», qui signifie «système de contrôle de version distribué».
Patrick McElhaney
Je veux dire un système de contrôle de version distribué.
tatsuhirosatou le

Réponses:

237

Heureusement pour ceux d'entre nous qui sont encore obligés d'utiliser CVS, git fournit de très bons outils pour faire exactement ce que vous voulez faire. Mes suggestions (et ce que nous faisons ici à $ work):

Création du clone initial

Utilisez git cvsimportpour cloner l'historique des révisions CVS dans un référentiel git. J'utilise l'invocation suivante:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

L' -Aoption est facultative, mais elle permet de donner à votre historique des révisions importé de CVS un aspect plus git (voir man git-cvsimportpour plus d'informations sur la configuration).

Selon la taille et l'historique du référentiel CVS, cette première importation prendra TRES longtemps. Vous pouvez ajouter un -v à la commande ci-dessus si vous voulez avoir la tranquillité d'esprit que quelque chose se passe réellement.

Une fois ce processus terminé, vous aurez une masterbranche qui devrait refléter HEAD de CVS (à l'exception que git cvsimportpar défaut ignore les 10 dernières minutes de commits pour éviter d'attraper un commit à moitié terminé). Vous pouvez ensuite utiliser git loget friends pour examiner l'historique entier du référentiel comme s'il utilisait git depuis le début.

Ajustements de configuration

Il y a quelques ajustements de configuration qui faciliteront les importations incrémentielles de CVS (ainsi que les exportations) à l'avenir. Ceux-ci ne sont pas documentés sur la git cvsimportpage de manuel, donc je suppose qu'ils pourraient changer sans préavis mais, FWIW:

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

Toutes ces options peuvent être spécifiées sur la ligne de commande afin que vous puissiez ignorer cette étape en toute sécurité.

Importations incrémentielles

La suite git cvsimportdevrait être beaucoup plus rapide que la première invocation. Cependant, il effectue un cvs rlogsur chaque répertoire (même ceux qui ne contiennent que des fichiers Attic), cela peut donc prendre quelques minutes. Si vous avez spécifié les configurations suggérées ci-dessus, tout ce que vous avez à faire est d'exécuter:

% git cvsimport

Si vous n'avez pas configuré vos configurations pour spécifier les valeurs par défaut, vous devrez les spécifier sur la ligne de commande:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

Quoi qu'il en soit, deux choses à garder à l'esprit:

  1. Assurez-vous que vous êtes dans le répertoire racine de votre référentiel git. Si vous êtes ailleurs, il essaiera de faire un nouveau cvsimportqui prendra à nouveau une éternité.
  2. Assurez-vous que vous êtes sur votre masterbranche afin que les modifications puissent être fusionnées (ou rebasées) dans vos branches locales / thématiques.

Faire des changements locaux

En pratique, je recommande de toujours apporter des modifications sur les branches et de ne fusionner que masterlorsque vous êtes prêt à exporter ces modifications vers le référentiel CVS. Vous pouvez utiliser le workflow de votre choix sur vos branches (fusion, rebasage, écrasement, etc.) mais bien sûr, les règles de rebasage standard s'appliquent: ne rebasez pas si quelqu'un d'autre a basé ses modifications sur votre branche.

Exportation des modifications vers CVS

La git cvsexportcommitcommande vous permet d'exporter un seul commit vers le serveur CVS. Vous pouvez spécifier un seul ID de validation (ou tout ce qui décrit une validation spécifique telle que définie dans man git-rev-parse). Un diff est ensuite généré, appliqué à une extraction CVS puis (éventuellement) validé dans CVS en utilisant le cvsclient réel . Vous pouvez exporter chaque micro-commit sur vos branches thématiques, mais en général, j'aime créer un commit de fusion sur un commit à jour masteret exporter ce commit de fusion unique vers CVS. Lorsque vous exportez un commit de fusion, vous devez indiquer à git quel parent de commit utiliser pour générer le diff. De plus, cela ne fonctionnera pas si votre fusion était une avance rapide (voir la section "COMMENT FONCTIONNE LA FUSION" man git-mergepour une description d'une fusion à avance rapide). Vous devez donc utiliser le--no-ffoption lors de l'exécution de la fusion. Voici un exemple:

# 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

Vous pouvez voir la signification de chacune de ces options sur la page de manuel de git-cvsexportcommit . Vous avez la possibilité de définir l' -woption dans votre configuration git:

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

Si le correctif échoue pour une raison quelconque, mon expérience est que vous ferez probablement (malheureusement) mieux de copier les fichiers modifiés manuellement et de les valider à l'aide du client cvs. Cependant, cela ne devrait pas se produire si vous vous assurez que masterCVS est à jour avant de fusionner votre branche thématique.

Si la validation échoue pour une raison quelconque (problèmes de réseau / autorisations, etc.), vous pouvez prendre la commande imprimée sur votre terminal à la fin de la sortie d'erreur et l'exécuter dans votre répertoire de travail CVS. Cela ressemble généralement à ceci:

% cvs commit -F .msg file1 file2 file3 etc

La prochaine fois que vous effectuez un git cvsimport(attendre au moins 10 minutes), vous devriez voir le correctif de votre commit exporté réimporté dans votre référentiel local. Ils auront des ID de commit différents puisque le commit CVS aura un horodatage différent et éventuellement un nom de committer différent (selon que vous avez configuré un fichier auteurs dans votre initiale cvsimportci-dessus).

Cloner votre clone CVS

Si vous avez plus d'une personne devant faire le cvsimport, il serait plus efficace d'avoir un seul référentiel git qui effectue le cvsimport et que tous les autres référentiels soient créés en tant que clone. Cela fonctionne parfaitement et le référentiel cloné peut effectuer des commandes cvsexport comme décrit ci-dessus. Il existe cependant une réserve. En raison de la manière dont les validations CVS reviennent avec différents ID de validation (comme décrit ci-dessus), vous ne voulez pas que votre branche clonée suive le référentiel git central. Par défaut, voici comment git cloneconfigurer votre référentiel, mais cela est facilement résolu:

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

Après avoir supprimé ces configurations, vous devrez explicitement dire où et quoi extraire lorsque vous souhaitez extraire de nouveaux commits depuis le référentiel central:

% git pull origin master

Dans l'ensemble, j'ai trouvé que ce flux de travail était assez gérable et que la "prochaine meilleure chose" lors d'une migration complète vers git n'est pas pratique.

Brian Phillips
la source
3
Je vous remercie. Cela m'a énormément aidé, en particulier le conseil sur l'utilisation d'une fusion non rapide pour regrouper les modifications de CVS en un seul commit.
skiphoppy
8
Pour mémoire, l'option -A que vous suggérez d'utiliser pour git-cvsimport est mentionnée dans la page de manuel comme étant "non recommandée ... si vous avez l'intention d'exporter à nouveau les modifications vers CVS plus tard avec git-cvsexportcommit (1)". Dans mon cas, j'aime vraiment la façon dont les auteurs sortent tels quels.
skiphoppy
2
Merci pour les conseils. Une chose pratique que j'ai faite est d'ajouter "cvs =! Git cvsimport -k -a" sous [alias] dans mon .gitconfig. Cela permet à "git cvs" de DTRT (du haut de l'arbre).
bstpierre
1
Si vous manquez git cvsimportsur Debian, essayezapt-get install git-cvs
Tino
5
Mac OSX mavricks manque entièrement de cvs et il semble que git cvsimport dépende des cvs Initialized empty Git repository in /Users/gus/projects/foo/foobar/.git/ Can't exec "cvsps": No such file or directory at /Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git-cvsimport line 777. Could not start cvsps: No such file or directory git cvsimport: fatal: cvsps reported errorDonc, malheureusement, cela ne vous permet pas de contourner l'absence de CVS :(
Gus
22

Vous ne devez pas faire confiance aveuglément à cvsimport et vérifier si l'arborescence importée correspond à ce qui se trouve dans le dépôt CVS. J'ai fait cela en partageant le nouveau projet en utilisant le plug-in eclipse CVS et j'ai constaté qu'il y avait des incohérences.

Deux validations qui ont été effectuées en moins d'une minute avec le même message de validation (afin de restaurer un fichier supprimé à tort) ont été regroupées en une seule grande validation, ce qui a entraîné un fichier manquant dans l'arborescence.

J'ai pu résoudre ce problème en modifiant le paramètre «fuzz» à moins d'une minute.

exemple:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

ligne du bas: vérifiez votre arbre après l'importation

shil88
la source
3

En plus de la réponse de Brian Phillips: il y a aussi git-cvsserver qui fonctionne comme le serveur CVS mais qui accède en fait au référentiel git ... mais il a quelques limitations.

Jakub Narębski
la source