= Work with the CVS repository using Git = This is a short memo on how to work with the CVS repository using Git. Please note this is still very rough contents in terms of code testing. <> == Requirements == Basic understanding of followings are prerequisites: * DebianPkg:git * DebianPkg:cvs == Work with the CVS repository using git == You may wish to use the convenience of your local git repository when you update an upstream source tree maintained in the CVS system. Of course, you can set up the full repository history of CVS in the local repository and track the CVS HEAD in your local git repository as the remote branch, e.g., as cvs/master. In short, this is slow and cumbersome. I will explain this later in "Approach 2" which is also the usual case documented elsewhere. For simplicity, I use following variables. {{{ CVSROOT=${USER}@${HOST}:${PATH_TO_CVSREPO} CWD=`pwd` }}} == Approach 1: only future changes == Let's worry only future changes with following focuses for simplicity: * do not worrying about the patch-set history * avoid running cvsps for processing speed * use the "-W" option to share a single directory between the CVS and git * use the "-c" option to multiple commits automatically. Here, you need to track CVS on "master" branch of git and work on "rebase" branch of git. This can be realized as: === make simple CVS checkout and make it a git repository (1st run only) === {{{ $ cvs -d :ext:${CVSROOT} checkout -P -kk $MODULE $ cd $MODULE $ git init; git add .; git commit -m "initial import" $ echo "CVS" > .git/info/exclude $ git checkout -b rebase }}} NOTE: All CVS directories are excluded from the git repository management. === update the git master branch to the latest CVS (non-1st run only) === {{{ $ git reset --hard master && git clean -f $ cvs update -PdA -kk $ git add . ; git commit -m "new cvs HEAD" $ git checkout rebase $ git reset --hard rebase && git clean -f }}} === start hacking the source on master === {{{ $ vim foo.txt $ git commit -a -m "commit for foo" $ vim bar.txt $ git commit -a -m "commit for bar" ... (test code etc.) $ vim baz.txt $ git commit -a -m "commit for baz" }}} === update to the latest CVS (to be sure) === {{{ $ git checkout master $ git reset --hard master && git clean -f $ cvs update -PdA -kk $ git add . ; git commit -m "new cvs HEAD" $ git checkout rebase $ git reset --hard rebase && git clean -f }}} === rebase to the latest CVS and organize commit candidates === {{{ $ git rebase -i master ... }}} === commit as a series of commits === {{{ $ git cherry master rebase | sed -n 's/^+ //p' | xargs -l1 \ git cvsexportcommit -ckpvW }}} This commits each git change set as a single set of CVS commit. == Approach 2: synchronized full history of changes == This approach requires to set up 3 directories to be efficient with the CVS data transaction. Let's arrange them as follows under ${CWD}/: * ${CWD}/gitdir/ * a local git repository managed by git-cvsimport without CVS/ directories * ${CWD}/cvsdir/ * a local checkout from the CVS repository with CVS/ directories * ${CWD}/rsyncdir/ * a full local copy of the CVS repository Overview of the workflow is the following. {{{ 1) 2) 3) Remote CVS -> Local CVS -+-> git-cvsimport (cvsps) -> hack ... + ^ | | | +-> cvs checkout -------------------> + | | +<------------------ git-cvsexportcommit <-------------+ 4) }}} === Create a local copy of the CVS repository === {{{ $ rsync -avS --delete --delay-updates --rsh=ssh ${CVSROOT}/. rsyncdir }}} You should see files under the following directories: * ${CWD}/rsyncdir/CVSROOT * ${CWD}/rsyncdir/${MODULE} === Create a local git repository and a local checkout from the CVS repository === {{{ $ git cvsimport -akmRv -d ${CWD}/rsyncdir -C gitdir -r cvs $MODULE $ cvs -d ${CWD}/rsyncdir checkout -P -kk -d cvsdir $MODULE }}} The git-cvsimport command imports the full history of changes to the local git repository and allows to synchronize it continuously with the upstream CVS. The upstream CVS repository data without CVS/ directories is tracked on the remote branch called cvs/master if "-r cvs" option is used. === Hack code while using git === {{{ $ cd ${CWD}/gitdir ... hack on master branch starting at remote branch cvs/master $ cd ${CWD} $ rsync -avS --delete --delay-updates --rsh=ssh ${CVSROOT}/. rsyncdir $ cd ${CWD}/cvsdir $ cvs -d ${CWD}/rsyncdir update -PdA -kk $MODULE $ cd ${CWD}/gitdir $ git rebase -i cvs/master ... resolve conflicts and clean up history }}} === Merge pending patches into CVS automatically === {{{ $ git cherry cvs/master master | sed -n 's/^+ //p' | xargs -l1 \ git cvsexportcommit -ckpuv -d $CVSROOT -w ${CWD}/cvsdir/ $ rm -rf ${CWD}/cvsdir }}} The "-d $CVSROOT" is required since CVS is used in an asymmetric fashion. == git-cvs == I am writing a git-cvs script to ease bidirectional operations between a single CVS tree and git. Download [[https://github.com/osamuaoki/git-cvs|git-cvs script]] and put it as git-cvs in your $PATH. See "git cvs help" for what it does. This takes care lots of sanity checks and corner cases. === approach 1 === {{{ $ git cvs init :ext:${CVSROOT} $MODULE $ cd $MODULE ... hack hack $ git commit -a -m "change set 1" $ git cvs dcommit ... long time $ git cvs update ... }}} === approach 2 === {{{ $ git cvs sync ${CVSROOT} $MODULE $ cd gitdir ... hack hack $ git commit -a -m "change set 1" $ git cvs dcommit ... long time $ git cvs update ... }}} == See also: == * [[http://stackoverflow.com/questions/584522/how-to-export-revision-history-from-mercurial-or-git-to-cvs|How to export revision history from mercurial or git to cvs?]] * [[http://pkp.sfu.ca/wiki/index.php/HOW-TO_import_and_export_to_and_from_Git_and_CVS|HOW-TO import and export to and from Git and CVS]] * [[https://arkaitzj.wordpress.com/2009/06/15/how-to-use-a-cvs-server-from-a-git-client/|How to use a CVS server from a git client]]