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 lorsque nous terminons ou peut-être de temps en temps, nous voulons commiter notre code et tout l'historique de nos révisions dans cvs. Nous n'avons pas d'accès en écriture au repo cvs du projet et nous ne pouvons pas commiter très fréquemment. Quel outil pouvons-nous utiliser pour exporter notre historique de révision vers cvs ? Actuellement, nous pensions utiliser git ou mercurial mais nous pourrions utiliser un autre vcs distribué si cela pouvait faciliter l'exportation.
Réponses
Trop de publicités?Heureusement pour ceux d'entre nous qui sont toujours 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
Utilice git cvsimport
pour cloner l'historique des révisions CVS dans un dépôt 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
El -A
est facultative, mais elle permet de rendre l'historique des révisions importé de CVS plus proche de celui de git (cf. man git-cvsimport
pour plus d'informations sur la façon dont cela est mis en place).
Selon la taille et l'historique du dépôt CVS, cette première importation prendra un TRES long moment. Vous pouvez ajouter un -v à la commande ci-dessus si vous voulez avoir la certitude que quelque chose est en train de se passer.
Une fois ce processus achevé, vous aurez une master
qui devrait refléter le HEAD de CVS (à l'exception de la branche git cvsimport
par défaut, ignore les 10 dernières minutes de commits pour éviter d'attraper un commit qui est à moitié terminé). Vous pouvez alors utiliser git log
et amis pour examiner l'historique complet du dépôt comme s'il avait utilisé git depuis le début.
Ajustements de la configuration
Il y a quelques ajustements de configuration qui rendront les importations incrémentielles depuis CVS (ainsi que les exportations) plus faciles à l'avenir. Elles ne sont pas documentées sur le site git cvsimport
donc je suppose qu'ils pourraient changer sans préavis, mais, pour info.. :
% 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, vous pouvez donc sauter cette étape.
Importations incrémentielles
Par la suite, git cvsimport
devrait être beaucoup plus rapide que la première invocation. Cependant, elle effectue un cvs rlog
sur chaque répertoire (même ceux qui n'ont que des fichiers en Attic
), ce qui peut 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 paramétré 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 :
- Assurez-vous que vous êtes dans le répertoire racine de votre dépôt git. Si vous êtes ailleurs, il essaiera de faire un nouveau
cvsimport
qui prendra encore une fois une éternité. - Assurez-vous que vous êtes sur votre
master
afin que les changements puissent être fusionnés (ou rebasés) dans vos branches locales/sujets.
Apporter des changements locaux
En pratique, je recommande de toujours faire des changements sur les branches et de ne fusionner que vers master
lorsque vous êtes prêt à exporter ces modifications vers le référentiel CVS. Vous pouvez utiliser le flux de travail que vous voulez sur vos branches (fusion, rebasage, écrasement, etc.) mais bien sûr les règles standard de rebasage s'appliquent : ne rebasez pas si quelqu'un d'autre a basé ses changements sur votre branche.
Exporter des changements vers CVS
El git cvsexportcommit
vous permet d'exporter un seul commit vers le serveur CVS. Vous pouvez spécifier un seul ID de commit (ou tout ce qui décrit un commit spécifique tel que défini dans le fichier man git-rev-parse
). Un diff est alors généré, appliqué à un checkout CVS et ensuite (optionnellement) commité dans CVS en utilisant l'adresse réelle de l'utilisateur. cvs
client. Vous pouvez exporter chaque micro-commande sur vos branches de sujet mais, en général, j'aime créer une commande de fusion sur une branche à jour. master
et exporter ce seul commit de fusion vers CVS. Lorsque vous exportez un commit de fusion, vous devez indiquer à git quel commit parent utiliser pour générer la différence. De plus, cela ne fonctionnera pas si votre fusion était un fast-forward (voir la section "COMMENT FONCTIONNE UNE FUSION" du document man git-merge
pour une description d'une fusion avec avance rapide), vous devez donc utiliser la fonction --no-ff
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 ce que chacune de ces options signifie sur le site Web de la Commission européenne. Page de manuel de git-cvsexportcommit . Vous avez la possibilité de définir le -w
dans votre configuration git :
% git config cvsexportcommit.cvsdir /path/to/cvs/checkout
Si le patch échoue pour une raison quelconque, mon expérience m'a montré qu'il est (malheureusement) préférable de copier manuellement les fichiers modifiés et de les valider à l'aide du client cvs. Cela ne devrait pas arriver, cependant, si vous vous assurez que master
est à jour avec CVS avant de fusionner votre branche de sujet.
Si le commit échoue pour une raison quelconque (problèmes de réseau/permissions, etc), vous pouvez prendre la commande affichée dans 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 à quelque chose comme ceci :
% cvs commit -F .msg file1 file2 file3 etc
La prochaine fois que vous ferez un git cvsimport
(en attendant au moins 10 minutes) vous devriez voir le patch de votre commit exporté réimporté dans votre dépôt local. Ils auront des ID de commit différents puisque le commit CVS aura un horodatage différent et peut-être un nom de committeur différent (selon que vous avez mis en place un fichier d'auteurs dans votre version initiale de CVS). cvsimport
ci-dessus).
Cloner votre clone CVS
Si plus d'une personne a besoin de faire le cvsimport
Il serait plus efficace d'avoir un seul dépôt git qui effectue le cvsimport et d'avoir tous les autres dépôts créés comme clone. Cela fonctionne parfaitement et le dépôt cloné peut effectuer des cvsexportcommits comme décrit ci-dessus. Il y a cependant un problème. En raison de la façon dont les commits CVS reviennent avec des ID de commit différents (comme décrit ci-dessus), vous ne voulez pas que votre branche clonée suive le dépôt git central. Par défaut, c'est ainsi que git clone
configure votre dépôt, mais il est facile d'y remédier :
% 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 indiquer explicitement où et de quoi tirer lorsque vous voudrez tirer de nouveaux commits du dépôt central :
% git pull origin master
Dans l'ensemble, j'ai trouvé que ce flux de travail était tout à fait gérable et qu'il constituait la "meilleure solution suivante" lorsque la migration complète vers git n'était pas pratique.
Vous ne devriez pas faire confiance cvsimport aveuglément et vérifier si l'arbre importé correspond à ce qui se trouve dans le repo CVS. J'ai fait cela en partageant le nouveau projet à l'aide du plug-in CVS d'eclipse et j'ai constaté qu'il y avait des incohérences
Deux commits effectués en moins d'une minute avec le même message de commit (afin de rétablir un fichier supprimé par erreur) ont été regroupés en un seul gros commit, ce qui a entraîné la disparition d'un fichier de l'arbre
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
la ligne de fond : vérifiez votre arbre après l'importation
En plus de la réponse de Brian Phillips : il y a aussi git-cvsserver qui fonctionne comme un serveur CVS mais qui accède au dépôt git... mais il a quelques limitations.