28 votes

Comment rétablir un changement important dans le CVS ?

Un de mes collègues a complètement chamboulé le contenu d'un répertoire de notre dépôt CVS principal. J'ai besoin de remettre tout le module dans l'état où il était à la fin de l'année dernière. Quelle est la commande CVS pour faire cela, s'il vous plaît ?

Il a ajouté et supprimé des centaines de fichiers, donc un simple "copier les fichiers de l'ancien checkout et commit" n'est pas suffisant.

J'ai RTFM et STFW, et j'ai essayé ceci :

cvs co modulename  # Note no -P option
cvs up -jHEAD -jMAIN:2008-12-30 modulename

Mais cela ne fonctionne pas - les nouveaux fichiers qu'il a créés sont supprimés, mais les anciens fichiers et répertoires ne sont pas ressuscités. (Je ne l'ai pas committé).

Je peux probablement écrire un shell script pour cela, mais cette fonctionnalité doit sûrement être déjà dans le CVS ?

Mise à jour : Quelques clarifications :

  • Je peux obtenir un caisse locale du module à une date précise. La question est de savoir comment récupérer cela dans le CVS.

  • J'ai des sauvegardes, mais l'intérêt d'un système de contrôle de révision comme CVS est qu'il est censé être facile d'obtenir tout état historique. La prochaine fois que quelque chose comme ça se produit, je n'aurai peut-être pas la chance d'avoir des sauvegardes (par exemple, les sauvegardes sont quotidiennes, donc je peux perdre jusqu'à une journée de travail).

  • Je sais que CVS est vieux, et que nous devrions passer à quelque chose de plus récent. Mais dans une grande équipe avec un grand nombre d'outils basés sur CVS (scripts de vérification et de construction, serveur de construction nocturne, etc.), le coût en temps d'une telle migration est considérable. (Évaluation, mise à jour des scripts, tests, migration, formation, perte de temps des développeurs, maintien des deux systèmes en parallèle car CVS serait toujours nécessaire pour les anciennes branches). C'est pourquoi cette opération doit être planifiée et programmée par la direction.

Mise à jour n°2 : Je vais lancer une prime sur ce sujet. Pour bénéficier de la prime, vous devez expliquer comment revenir en arrière en utilisant les commandes CVS normales, pas avec un shell script.

Mise à jour n°3 : Le serveur est CVS 1.12.13 . L'accès se fait via pserver. Je peux utiliser la même version de CVS sur un PC Linux, ou l'application CVSNT 2.0.51d sur Windows.

27voto

Ralph Points 2537

En fait, votre approche initiale était très proche de la solution. Le problème est que la jointure basée sur la date ne gère pas correctement les fichiers et répertoires supprimés. Vous devez d'abord définir une balise pour la base de code que vous voulez joindre :

mkdir code_base1 && cd code_base1
cvs co -D "2008-12-30" modulename
cvs tag code_base_2008_12_30

Maintenant, faites la jointure basée sur les tags, en soustrayant tous les changements entre maintenant et 2008-12-30 :

cd .. && mkdir code_base2 && cd code_base2
cvs co modulename
cvs update -d -j HEAD -j code_base_2008_12_30  # use -d to resurrect deleted directories

Comparez le contenu de la base de code 1 et de la base de code 2. Ils devraient être identiques, à l'exception des méta-informations CVS. Enfin, livrez le code tel qu'il était le 30-12-2008 en tant que nouveau HEAD :

cvs commit -m "Revert all changes this year"

Notez que le marquage du code que vous souhaitez joindre de cette manière ne fonctionnera pas, car rtag ne gère pas non plus correctement les fichiers et répertoires supprimés, lors de l'utilisation de -D :

cvs rtag -D "2008-12-30" code_base_2008_12_30 modulename

4voto

Keltia Points 8104

Il y a plusieurs problèmes avec CVS et vous les frappez avec un tel problème.

  1. CVS est orienté fichier, pas de concept de changeset ou snasphot. Cela signifie que les changements tels que celui que vous voulez annuler sont un peu difficiles à gérer. Les commits sont atomiques dans un répertoire donné, pas en dehors.

  2. Les répertoires ne sont pas classés par version. Cela signifie que les répertoires vides seront supprimés (si vous mettez à jour avec -P ) et que vous devez spécifier -d pour les créer à la sortie/à la mise à jour.

Donc, pour répondre à votre question, les dates sont probablement le seul moyen de faire face au fait que vous n'avez pas utilisé de balises pour créer une version pauvre de changeset.

Mon commentaire sur les sauvegardes est qu'il peut être plus facile de récupérer l'ensemble du repo à partir des sauvegardes que d'essayer de corriger des choses pour lesquelles CVS n'est pas vraiment compétent.

Je vous encourage - mais c'est un autre sujet - à changer de contrôle de version dès que possible. Croyez-moi, je m'occupe de CVS depuis longtemps au sein de la Projet FreeBSD et apprendre très vite à quel point le CVS est détestable... Voir aquí pour connaître mon point de vue sur les logiciels de contrôle de version.

2voto

JW. Points 17361

Je pense que votre deuxième commande devrait également être un checkout, plutôt qu'une mise à jour. Je ne peux pas justifier cela par la logique, car il n'y a pas de logique dans le monde de CVS, mais cela a fonctionné pour moi. Essayez ceci :

cvs co -P modulename
cvs co -P -jHEAD -jMAIN:2008-12-30 modulename

Si vous retournez une branche autre que HEAD, par exemple X, passez l'argument -rX dans les deux commandes :

cvs co -P -rX modulename
cvs co -P -rX -jHEAD -jMAIN:2008-12-30 modulename

1voto

user9876 Points 5385

Je suis toujours intéressé de savoir s'il existe un moyen plus facile. (Il doit sûrement y avoir un moyen plus facile). Ce que j'ai fini par faire, sur un PC Linux en utilisant bash :

# Get woking copy we're going to change
cd ~/work
rm -rf modulename
cvs up -dP modulename
cd modulename

# Remove all files
find . -name CVS -prune -o -type f -print | xargs cvs rm -f

# Get the old revision
cd ~
mkdir scratch
cd scratch
cvs -q co -D 2008-12-31 modulename
cd modulename

# Copy everything to the working dir and do "cvs add" on it
find . -name CVS -prune -o -type f -print | \
    xargs tar c | \
    (cd ~/work/modulename && tar xv | \
    xargs cvs add)

# Check everything is OK before we commit
cd ~/work/modulename
cvs -nq up

# it gave me an error on readme.txt because I'd deleted and then added it, so:
mv readme.txt x # save good rev
cvs add readme.txt # resurrect the bad rev
mv x readme.txt # clobber file with good rev

# Commit it
cvs commit -m "Revert all changes this year"

# Delete now-empty directories
cvs -q up -dP

# Double-check everything is back how it was
diff -ur -xCVS ~/scratch/modulename ~/work/modulename

J'ai ensuite découvert qu'il y avait encore des différences - mon collègue avait ajouté des noms de fichiers contenant des espaces, qui n'ont pas été supprimés par le processus ci-dessus. J'ai dû les supprimer séparément. (J'aurais dû utiliser find ... -print0 plutôt que -print et a passé le -0 argument pour xargs . Je n'avais pas réalisé qu'il y avait des fichiers avec des espaces.)

1voto

smcameron Points 1864

Vous pourriez chercher dans les cvsps. Cherchez sur Google.

De plus, avec quilt (ou les patchscripts d'Andrew Morton, qui est ce qu'était quilt au départ) et cvsps, une approximation très proche des changesets peut être obtenue.

véase http://geocities.com/smcameron/cvs_changesets.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X