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 cvsimport
per 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' -A
opzione è facoltativa ma aiuta a rendere la cronologia delle revisioni importata da CVS più simile a git (vedere man git-cvsimport
per 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 master
ramo che dovrebbe riflettere l'HEAD di CVS (con l'eccezione che git cvsimport
per impostazione predefinita ignora gli ultimi 10 minuti di commit per evitare di catturare un commit che è finito a metà). È quindi possibile utilizzare git log
e 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 cvsimport
pagina 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 cvsimport
dovrebbe essere molto più veloce della prima chiamata. Tuttavia, esegue un'operazione cvs rlog
su 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:
- Assicurati di essere nella directory principale del tuo repository git. Se sei altrove, proverà a fare un nuovo
cvsimport
che richiederà ancora un'eternità.
- Assicurati di essere nel tuo
master
ramo 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 master
quando 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 cvsexportcommit
comando 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 cvs
client effettivo . Potresti esportare ogni micro commit sui tuoi topic branch, ma generalmente mi piace creare un merge commit su un aggiornamento master
ed 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-merge
per una descrizione di un'unione con avanzamento rapido), quindi devi usare il--no-ff
opzione 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' -w
opzione 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 master
essere 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 cvsimport
sopra).
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 clone
configura 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.