Come esportare la cronologia delle revisioni da mercurial o git a cvs?


100

Lavorerò con altre persone sul codice di un progetto che utilizza cvs. Vogliamo usare una vcs distribuita per fare il nostro lavoro e quando finiamo o forse ogni tanto vogliamo inviare il nostro codice e tutta la nostra cronologia delle revisioni a cvs. Non abbiamo accesso in scrittura al repository cvs del progetto, quindi non possiamo eseguire il commit molto frequentemente. Quale strumento possiamo usare per esportare la nostra cronologia delle revisioni in cvs? Al momento stavamo pensando di utilizzare git o mercurial, ma potremmo usare un altro vcs distribuito se potesse rendere più semplice l'esportazione.


Quando dici "CVS distribuito" penso che intendi "VCS distratto" o "DVCS", che sta per "sistema di controllo della versione distribuito".
Patrick McElhaney

Intendo un sistema di controllo della versione distribuito.
tatsuhirosatou

Risposte:


237

Fortunatamente per quelli di noi che sono ancora costretti a usare CVS, git fornisce strumenti abbastanza buoni per fare esattamente quello che vuoi fare. I miei suggerimenti (e cosa facciamo qui a $ work):

Creazione del clone iniziale

Utilizzare git cvsimportper clonare la cronologia delle revisioni CVS in un repository git. Uso la seguente invocazione:

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

L' -Aopzione è facoltativa ma aiuta a rendere la cronologia delle revisioni importata da CVS più simile a git (vedere man git-cvsimportper maggiori informazioni su come è impostata).

A seconda delle dimensioni e della cronologia del repository CVS, questa prima importazione richiederà molto tempo. Puoi aggiungere -v al comando precedente se vuoi la tranquillità che qualcosa sta effettivamente accadendo.

Una volta completato questo processo, avrai un masterramo che dovrebbe riflettere l'HEAD di CVS (con l'eccezione che git cvsimportper impostazione predefinita ignora gli ultimi 10 minuti di commit per evitare di catturare un commit che è finito a metà). È quindi possibile utilizzare git loge amici per esaminare l'intera cronologia del repository proprio come se avesse utilizzato git dall'inizio.

Modifiche alla configurazione

Ci sono alcune modifiche alla configurazione che renderanno più facili le importazioni incrementali da CVS (così come le esportazioni) in futuro. Questi non sono documentati nella git cvsimportpagina man quindi suppongo che potrebbero cambiare senza preavviso ma, FWIW:

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

Tutte queste opzioni possono essere specificate sulla riga di comando in modo da poter saltare questo passaggio in sicurezza.

Importazioni incrementali

Il successivo git cvsimportdovrebbe essere molto più veloce della prima chiamata. Tuttavia, esegue un'operazione cvs rlogsu ogni directory (anche quelle che contengono solo file Attic), quindi può richiedere ancora alcuni minuti. Se hai specificato le configurazioni suggerite sopra, tutto ciò che devi fare è eseguire:

% git cvsimport

Se non hai impostato le tue configurazioni per specificare i valori predefiniti, dovrai specificarli nella riga di comando:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

In ogni caso, due cose da tenere a mente:

  1. Assicurati di essere nella directory principale del tuo repository git. Se sei altrove, proverà a fare un nuovo cvsimportche richiederà ancora un'eternità.
  2. Assicurati di essere nel tuo masterramo in modo che le modifiche possano essere unite (o riassegnate) nei tuoi rami locali / argomenti.

Apportare modifiche locali

In pratica, raccomando di apportare sempre modifiche sui rami e di unirle solo masterquando sei pronto per esportare quelle modifiche nel repository CVS. Puoi utilizzare qualsiasi flusso di lavoro desideri sui tuoi rami (fusione, ribasatura, schiacciamento, ecc.) Ma ovviamente si applicano le regole standard di ribasatura: non ribasare se qualcun altro ha basato le proprie modifiche sul tuo ramo.

Esportazione delle modifiche in CVS

Il git cvsexportcommitcomando ti consente di esportare un singolo commit sul server CVS. È possibile specificare un singolo ID commit (o qualsiasi cosa che descriva un commit specifico come definito in man git-rev-parse). Viene quindi generata una differenza, applicata a un checkout CVS e quindi (facoltativamente) impegnata in CVS utilizzando il cvsclient effettivo . Potresti esportare ogni micro commit sui tuoi topic branch, ma generalmente mi piace creare un merge commit su un aggiornamento mastered esportare quel singolo merge commit in CVS. Quando esporti un merge commit, devi dire a git quale commit genitore usare per generare il diff. Inoltre, questo non funzionerà se la tua unione è stata un avanzamento rapido (vedi la sezione "COME FUNZIONA UNIONE" di man git-mergeper una descrizione di un'unione con avanzamento rapido), quindi devi usare il--no-ffopzione quando si esegue l'unione. Ecco un esempio:

# 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

Puoi vedere il significato di ciascuna di queste opzioni nella pagina man di git-cvsexportcommit . Hai la possibilità di impostare l' -wopzione nella tua configurazione git:

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

Se la patch fallisce per qualsiasi motivo, la mia esperienza è che (sfortunatamente) probabilmente farai meglio a copiare manualmente i file modificati e ad impegnarti utilizzando il client cvs. Questo non dovrebbe accadere, tuttavia, se ti assicuri di masteressere aggiornato con CVS prima di unire il tuo topic branch in.

Se il commit fallisce per qualsiasi motivo (problemi di rete / permessi, ecc.), Puoi portare il comando stampato sul tuo terminale alla fine dell'output dell'errore ed eseguirlo nella tua directory di lavoro CVS. Di solito ha un aspetto simile a questo:

% cvs commit -F .msg file1 file2 file3 etc

La prossima volta che farai un git cvsimport(aspettando almeno 10 minuti) dovresti vedere la patch del tuo commit esportato reimportato nel tuo repository locale. Avranno ID commit diversi poiché il commit CVS avrà un timestamp diverso e possibilmente un nome di commit diverso (a seconda che tu abbia impostato un file autori nella tua iniziale cvsimportsopra).

Clonare il tuo clone di CVS

Se più di una persona ha bisogno di eseguire l'operazione cvsimport, sarebbe più efficiente avere un unico repository git che esegue cvsimport e che tutti gli altri repository siano creati come clone. Funziona perfettamente e il repository clonato può eseguire cvsexportcommits proprio come descritto sopra. C'è tuttavia un avvertimento. A causa del modo in cui i commit CVS vengono restituiti con diversi ID commit (come descritto sopra), non vuoi che il tuo ramo clonato tenga traccia del repository git centrale. Per impostazione predefinita, questo è il modo in cui git cloneconfigura il tuo repository ma questo è facilmente risolvibile:

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

Dopo aver rimosso queste configurazioni, dovrai dire esplicitamente da dove e cosa estrarre quando vuoi inserire nuovi commit dal repository centrale:

% git pull origin master

Nel complesso, ho trovato questo flusso di lavoro abbastanza gestibile e la "prossima cosa migliore" quando si migra completamente a git non è pratica.


3
Grazie. Questo mi ha aiutato immensamente, specialmente il suggerimento sull'uso di un'unione non fastforward per raggruppare le modifiche per CVS in un unico commit.
skiphoppy

8
Per la cronaca, l'opzione -A che suggerisci di usare per git-cvsimport è menzionata nella manpage come "non consigliata ... se intendi esportare nuovamente le modifiche in CVS in seguito con git-cvsexportcommit (1)." Nel mio caso, in realtà mi piace il modo in cui gli autori escono così come sono.
skiphoppy

2
Grazie per i suggerimenti. Una cosa utile che ho fatto è aggiungere "cvs =! Git cvsimport -k -a" sotto [alias] nel mio .gitconfig. Questo fa in modo che "git cvs" eseguirà il DTRT (dalla cima dell'albero).
bstpierre

1
Se ti manca git cvsimportsu Debian provaapt-get install git-cvs
Tino

5
I mavricks di Mac OSX mancano completamente di cv e sembra che git cvsimport dipenda da 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 errorQuindi, purtroppo, questo non ti aiuta a evitare l'assenza di CVS :(
Gus

22

Non dovresti fidarti ciecamente di cvsimport e controllare se l'albero importato corrisponde a quello che è nel repository CVS. L'ho fatto condividendo il nuovo progetto utilizzando il plug-in di eclipse CVS e ho scoperto che c'erano delle incongruenze ..

Due commit eseguiti in meno di un minuto con lo stesso messaggio di commit (al fine di ripristinare un file cancellato per errore) sono stati raggruppati in un unico grande commit, che ha portato a un file mancante dall'albero.

Sono stato in grado di risolvere questo problema modificando il parametro "fuzz" a meno di un minuto.

esempio:

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

linea di fondo: controlla il tuo albero dopo l'importazione


3

Oltre alla risposta di Brian Phillips: c'è anche git-cvsserver che funziona come il server CVS ma in realtà accede al repository git ... ma ha alcune limitazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.