Projects - Git Cvs Sync
How to commit changes to a CVS repo but secretly use git to do most of the real work. Or: how to limit your interaction with CVS to the absolute minimum.
We will use the Emacs CVS repository as an example. It is assumed that you have commit access to the CVS repo.
So you've decided that you would much rather be developing Emacs using git. Good choice. Here is one way to set it up.
The directory tree will look like this:
emacs/ git-emacs/ | This is the unofficial git repo for Emacs. cvs-emacs/ | This is the official CVS repo for Emacs. export-from-git | This is a handy script for syncing changes.
First, make your top-level directory, which I have called emacs here.
cd /path/to/my/projects mkdir emacs cd emacs
Check out either git://git.sv.gnu.org/emacs.git or
git://repo.or.cz/emacs.git. I use the former.
git clone $REPO mv emacs git-emacs
Get the CVS repo as well.
cvs -z3 -d:ext:YOURNAME@cvs.savannah.gnu.org:/sources/emacs co emacs mv emacs cvs-emacs
Save the following script to the file export-from-git (name it
whatever you like).
#!/bin/sh # # Export a commit from git to CVS. if test -z "$1" || test -n "$2"; then echo Incorrect number of arguments exit 1 fi export GIT_DIR=../git-emacs/.git git cvsexportcommit -c -p -v $1
If you want to update the git repo, and you have not committed any
local changes to the current branch, do git pull origin master.
If you have committed some changes that you'd like to keep, then do
git fetch and git rebase origin/master, assuming you are in the master
branch (or whatever branch in which your changes lie).
If you want to just throw away the local changes (for example, on a
branch where you stage changes before committing them to CVS), do git
reset --hard origin/master and git pull origin master. This allows
you to see a pretty diffstat when the pull is done. To replicate that
same diffstat, use git diff --stat master origin/master, replacing
"master" and "origin/master" as appropriate to indicate the two
markers to compare.
Branches can be set up however you like. Just be sure to use the
--no-track option to the git branch command if a branch by the same
name exists on the remote repo, and you do not want to automatically
update it with git pull. If you are careful like this, you can omit
the arguments to git pull to save typing.
First, bring up the output from git log so that you know which commit
IDs you want to sync to CVS.
Then update CVS using cd cvs-emacs; cvs up -dPR.
Now commit each change from oldest to most recent using the
../export-from-git script. The current directory should be cvs-emacs.
The first and only argument should be a single commit ID. This script
will try out the change, and then commit it if things are up-to-date.
Be sure to separate changes to ChangeLog files from other changes,
because they will undoubtedly have to be merged manually. If a commit
doesn't go through, remove the .dotest directory, fix up the file
manually, and do cvs commit -F .msg -- file1 file2 ... if you want to
keep the same commit message that is present in the git repo.
If the remote git repo you are using happens to lag behind for some reason, and there is a commit that you want to check in, there is a way to deal with it.
First, make a new git branch in the git-emacs repo called something
like fakesync and check it out. Then switch to the cvs-emacs
directory and run the following:
export GIT_DIR=../git-emacs/.git # If you need to remove files that should not be tracked in git, # do the next command, otherwise skip it. make maintainer-clean git add . git add -u . git commit -m "Fake sync from Emacs" unset GIT_DIR
Now rebase your changes against this new branch, run git log, and use
../export-to-git on any commits that you want to sync back to CVS.
Afterward, you can either ignore this branch or remove it.