As many of my readers know, I’m a Solaris and FreeBSD aficionado. Both operating systems bring many innovations to the table and make life easy for system administrators. Though FreeBSD switched to Subversion years ago for its code base (kernel and world), FreeBSD’s Ports tree is still using CVS. In this article, I will discuss how to create your own Git repo of the FreeBSD Ports tree.

I’m going to keep an up-to-date Git repo hosted at GitHub. The updating frequency will likely be at least once per day.


  • csup (comes with all base installs of FreeBSD)
  • git
  • cvscvt (copied to /usr/local/bin)

ZFS Setup I’m a big fan of ZFS. We’re going to create a few ZFS datasets: [shawn@fbsd-sec ~]$ zfs get -r -oname,property,value name,mountpoint rpool/ports_cvs NAME PROPERTY VALUE rpool/ports_cvs name rpool/ports_cvs rpool/ports_cvs mountpoint /ports_cvs rpool/ports_cvs/csup_db name rpool/ports_cvs/csup_db rpool/ports_cvs/csup_db mountpoint /ports_cvs/csup_db rpool/ports_cvs/cvsroot name rpool/ports_cvs/cvsroot rpool/ports_cvs/cvsroot mountpoint /ports_cvs/cvsroot rpool/ports_cvs/gitrepo name rpool/ports_cvs/gitrepo rpool/ports_cvs/gitrepo mountpoint /ports_cvs/gitrepo

Give the user account (we’ll use the account shawn in this article as an example) full access to each of these directories: for dir in `find /ports_cvs -type d`; do setfacl -m user:shawn:full_set:fd:allow $dir; done

Fetching the Ports Tree FreeBSD uses a utility called csup to download from cvs the ports repo. You’ll need to copy (and modify) the supfile found at /usr/share/examples/cvsup/cvs-supfile to /ports_cvs/cvs-supfile. I pasted my supfile as an example here. Change directory to /ports_cvs and run csup now and twiddle your thumbs for a couple hours: cd /ports_cvs; csup -L2 cvs-supfile

Converting to git Since this is our first run, we need to make the git repo. Change directory to /ports_cvs/gitrepo and run git init: cd /ports_cvs/gitrepo; git init. Next we’ll do the actual conversion from CVS to Git: cd /ports_cvs; cvscvt -e -k FreeBSD /ports_cvs/cvsroot/ports | GIT_DIR=gitrepo/.git git fast-import

After doing the conversion, you might have a dirty git checkout. Reset the checkout to HEAD: cd /ports_cvs/gitrepo; git reset --hard HEAD

Conclusion You’ve now fully converted the Ports tree from CVS to Git! You can now treat the git checkout as a normal git Ports tree.

Extra Info I’ve scripted doing all this so that I can run it as a nightly job. If you’d like to take a look at the script, take a look at my set of nightly scripts. Taking a look at the script will also help with understanding the commands I laid out above.