Using CVS With XCode

Source Code Management Made Easy


Justin Williams Skip to comments 29 Comments (Comments Closed Closed)

Justin Williams teaches all the developers how to take advantage of Xcode's source code management integration by setting up a local CVS repository on your Mac.

Have you ever been working on a project in Xcode, taken a direction in the code, and wished you hadn't? You sat there and just wished you could go back to the way your code was three days ago before you decided that bad idea was a really good one. Maybe you work in a team and were frustrated when your coworker was working on the same file you were and saved over the three hours worth of changes you had just made. Both of these issues would be nonexistent if you used some sort of version control in your coding projects. Version control is taken care of by some sort of source code management system. These applications keep track of version history, releases, code differences, and many other features. CVS (Concurrent Versions System) has been the de facto standard for version control for many years. Many companies, including Apple, use the technology to keep track of the changes made to code bases by their employees. CVS is bundled with MacOS X Panther, so it's not too difficult to get setup if you know a few things. First off, this article has a few requirements: MacOS X Panther 10.3.4. It may work on other versions, but my machine is only running the latest version, and have no means to test older updates. You will also need Xcode 1.2. You can get the latest version of Xcode from the Apple Developer Connection website. Finally, you are going to need a current project in Xcode. If you don't know how to create a project in Xcode, you probably don't need to be reading this anyway. A final suggestion. If you have a pre-existing project you are going to use for this tutorial, clean the target before importing the project into CVS. You don't want the build directory to tag along since its usually quite large and a waste of space. ### CVS Setup and Initialization Let's get started. First off we need to create our CVS repository. Open up a new instance of Terminal and type the following commands: sudo sh mkdir /usr/local/cvsrep chmod g+w /usr/local/cvsrep exit The repository is the place where CVS keeps copies of all of the files in your project. Think of it as a massive database of code changes. The chmod command gave the group you are in write access to the repository. To make sure you are in the correct group, use the 'groups' command in terminal. Next, you need to set your CVSROOT variable so that CVS knows where your repository is. In tcsh, open the .tcshrc file and add the following line: setenv CVSROOT "/usr/local/cvsrep" And in bash add the following line to .bash_profile: export CVSROOT=/usr/local/cvsrep Now that we have everything we need setup, let's initialize our new repository. cvs init Congratulations, you now have a working CVS repository! ### XCode Configuration The next step we need to take though is to update the cvswrappers file so that CVS understands that Xcode project files and other nontext files should be treated as such. Luckily, Apple bundles a cvswrappers file with the developer tools that will do just the trick. What we need to do is checkout the CVSROOT project, change into that directory, copy the new file in, commit, it, and then delete the local copy CVS created. cvs co CVSROOT cd CVSROOT cp /Developer/Tools/cvswrappers ./ cvs commit -m "New cvswrappers" cd .. rm -R CVSROOT The final step in getting this whole thing completed is to import your Xcode project into CVS. First, you need to move to your project's directory and use cvs import. cd ~/Project cvs import -m "Initial import" Project maczealots start The -m switch lets us give a small note as to what we are doing in the project. These notes are useful when you are going back in versions and what to see what a certain commit actually did. Project is the name of the project. This is the name you reference when you are checking out the project, committing files, etc. The vendor tag I used was maczealots. You can use whatever you want (usually a company name). The last start command tells CVS to get to work. With the project imported, we now need to get our local non-CVS copy out of the way so that there is no interference. What I do is just move the project to a folder under my Development folder with -PreCVS attached to the name. After that we are checking out a CVS copy of our project that we will work with. cd ~/Project cd .. mv Project Project-PreCVS cvs co Project If you look in your home directory, you should now have a copy of Project that came from the CVS repository. Open that project up in Xcode and we will go about setting it up to be CVS friendly. Once in Xcode, you'll see that your project looks identical to the way it did before. To enable CVS, you need to Get Info on your project. In the Project Info window you will see "Enable SCM" at the bottom. Select CVS from the popup menu. This will enable SCM. Click on the Edit... button and confirm that the CVS Tool Path is /usr/bin/cvs and that "Use ssh instead of rsh for external connections" is checked. This is important for when we use Rendezvous to share our project. Use ssh instead of rsh for external connections SCM WindowGo ahead and make some changes to some files. Once finished doing that, select SCM from the SCM menu. You will notice that any files that have been modified show up in this window. To commit these changes to the CVS repository, select Commit Changes from the SCM menu. Once committed, the files are removed from the SCM window. I am not going to devote much time to explaining all of the features of CVS because it is well documented already. For more information on CVS visit the project's website or read Open Source Development With CVS by Karl Fogel and Moshe Bar. It is available in PDF format under the GPL license. ### Remote Configuration Using SSH & Rendezvous If you are just using a single machine to do your development, you can stop here. If, however, you want to be able to access your repository from another Mac on your network, read on! I have an iBook that I like to sometimes sit around and do development work on. One of the problems I have is that its hard to keep the files on my G5 and my iBook up to date. Using CVS, this is a thing of the past. We will share our repository using ssh, a secure version of Telnet installed on every OS X machine. To access the repository from the laptop, Remote Login needs to be enabled on the machine that has the repository. To enable this, jump to the Sharing Pane in System Preferences and make sure Remote Login is checked. Next we need to set another variable in our shell configuration files. This time we are setting the CVS_RSH variable. If you are using tcsh, add this line to your .tcshrc file: setenv CVS_RSH "ssh" For those using bash, edit the .bash_profile file: export CVS_RSH=ssh I am using Rendezvous for simplicities sake. I have no desire to access my repository when I am away from my network. After all, I leave the house to get away from stuff like this. To get your computer's Rendezvous name, look under the Sharing Preference pane again. It should look something like this: Rendezvous Name Make sure you can get a connection from the laptop to your repository using ssh from the Terminal: ssh username@Gavin.local You should be asked if its ok to authenticate a key and then be prompted for a password. If you are able to connect, you are good. Quit that connection, but stay on your second machine. You need to set the CVS_RSH and CVSROOT environment variables on that machine as you did above. In tcsh, open the .tcshrc file and add the following line (replacing justin and Gavin.local with your values): setenv CVSROOT ":ext:justin@Gavin.local:/usr/local/cvsrep" setenv CVS_RSH "ssh" And in bash add the following line to .bash_profile: export CVSROOT=:ext:justin@Gavin.local:/usr/local/cvsrep export CVS_RSH=ssh You are also going to need to set SSH up so that it won't need to enter a password when accessing your repository's machine. XCode has some sort of issues when it comes to entering an authorization password that I could not get past. On your laptop enter the following commands ssh-keygen -t dsa Hit enter to accept the default values for each prompt. Next, you will need to copy the contents of the id_dsa.pub file so you can paste it into the authorized_keys file on the repository machine. On the client machine: cat ~/.ssh/id_dsa.pub (Copy the output) ssh justin@Gavin.local vi ~/.ssh/authorized_keys (Paste previous output and save the file) If you can now ssh to the repository machine without entering a password, you should have no trouble with XCode asking for a password. Make some edits on the remote machine and make sure you can commit them to the repository. ### Conclusion We have done some pretty neat things in this tutorial. We went from having our code saved on a single machine with no sort of history or sharing capability to a fully functional CVS repository with remote access capabilities. There is so much more to learn about CVS than I have taught you. To get a full understanding of the technology, please read the CVS book I referenced earlier. If you are going to use a tool, use it right and to its fullest potential. If you have any questions or comments on this article, please post them in the comments!

Justin WilliamsJustin Williams is founder and chief author for MacZealots. He switched to the Mac almost five years ago hasn't looked back since. When not blogging or coding, you can find him watching copious amounts of TV. Justin can be reached at

Reader Comments (29)

DISCLAIMER: The views expressed below are those of their authors and not necessarily endorsed or supported by MacZealots.com. In all cases, the comments provided here are offered as a courtesy and will be moderated. Any content deemed off-topic or offensive will be removed without notice. Posting a comment here boils down to two things: 1.) Think before you type 2.) Respect the thoughts of others. See our commenting guidelines and/or privacy policy for more information.

1 Mark Demma remarks:
#1) On July 16, 2004 4:26 PM

This article was very informative… have one question maybe some one out there has an answer … I have java developers with projects already checked into CVS. Was wondering how to make X-code take an already existing CVS project and use that as an X-code project.

2 Grant remarks:
#2) On July 16, 2004 4:56 PM

New users intending to use version control on their own developments might do better to use or at least look at subversion (http://subversion.tigris.org/) which improves on CVS, fixing a number of issues it has. Subversion comes with an excellent user guide - a PDF that is the same as the O’Reilly book. Apple says that subversion will be integrated with XCode 2, due sometime next year. In the meantime you’ll have to work it yourself outside of XCode.

(The reason I say “on their own developments” is that CVS is stil widely used on sourceforge, etc., and will be for some time I suspect. Not because CVS is better for that purpose, but just its the established thing.)

3 Justin Williams remarks:
#3) On July 16, 2004 6:49 PM

I am working on a Subversion tutorial as we speak. It’s about 75% done at the moment. Whenever XCode with Subversion support is released, I will probably put it online.

If, however, there is a demand for a command line tutorial, I can gladly put that up beforehand.

4 bg remarks:
#4) On July 17, 2004 5:39 AM

Nice one - thanks.

is it possible to access the cvs repository on my powerbook, from my windows machine?

If so how?

when will the article on subversion be available?

5 Justin Williams remarks:
#5) On July 17, 2004 8:03 AM

I don’t do Windows, and when it’s done.

6 Clint Ecker remarks:
#6) On July 17, 2004 12:54 PM

BG, check out WinCVS for using CVS on windows.

7 Carl Lindberg remarks:
#7) On July 17, 2004 8:00 PM

GUI apps will not read .bash_profile (or similar). There is an ~/.MacOSX/environment.plist file that can be used for that (loginwindow puts any settings there into the environment used to launch GUI apps). RCEnvironment is a pref pane to set them.

Generally though, for remote ssh stuff I really like to use the fsh wrapper instead (set CVS_RSH to “fsh”). It uses python, and needs to be installed on both client and server machines. It will prompt for a password the first time (I usually run a cvs command from the command line to trigger it), then it keeps the ssh connection open for any subsequent CVS commands (including those from GUI apps like Xcode). This makes for much faster connections since the SSH session doesn’t have to be set up each time, and there is an “fcp” wrapper for scp as well. fsh can be found at http://www.lysator.liu.se/fsh/fsh.html for those interested.

8 tunesmith remarks:
#8) On July 17, 2004 11:21 PM

I haven’t tried this step by step, but unless things are different with CVSROOT, you have to also “cvs add cvswrappers” before you commit it.

9 Menno Deij remarks:
#9) On July 21, 2004 1:56 AM

Not all versions of cvs support -t / -f flags.
This is what I got after changing the cvswrapper on an IRIX machine (where I happen to have my source repository):

cvs [server aborted]: -t/-f wrappers not supported by this version of CVS

Now the whole repository is mangled, no checkout/checkin possible. I hope to be able to set it right again.

10 Justin Williams remarks:
#10) On July 21, 2004 2:00 AM

I never said an OS X repository would work with anything but OS X. I haven’t tested it with anything but Panther.

11 Erwin remarks:
#11) On August 2, 2004 3:33 AM

Very good article (the best I read about this subject)… everything I should know to setup CVS… BUT
CVS button is checked by default when opening an new project… anyway to change it to Unchecked by default…. if I don’t want to use CVS at all ???

12 LaChoseInteractive remarks:
#12) On August 13, 2004 10:43 AM

For Subversion try the freeware SvnX by www.lachoseinteractive.net/en/community/subversion/.

13 Marcelo remarks:
#13) On August 19, 2004 6:36 PM

Call me a mac dummy, but by default, which shell do I have? I couldn’t find .bash_profile anywhere! These things should be spelled out, after all we are Mac users… ;-)

14 klktrk remarks:
#14) On September 2, 2004 2:12 AM

Thank you for the tutorial. There seems to be one problem in XCode, though. I have an external cvs account for my projects hosted on my Linux box. I don’t like using shared keys too much, so XCode asked for my password, which I, in my haste, typed in incorrectly. Now, even after quitting and restarting XCode, it keeps telling me the repository is unavailable (password denied), but there is no way for me to change the password I entered! I even removed my project, checked out a new one, opened up XCode, and still the same thing. Evidently, XCode caches the password somehow in the project file or whatnot, but gives you no way to edit it.

That’s pretty stupid, if you ask me (and I’m obviously stupid enough to not type my password correctly). But a word of warning to others, I guess.

I have now effectively screwed any possibility of integrating the SCM into my project in XCode, but have to use the command line (which is what I was used to anyway…).

15 hiro remarks:
#15) On October 17, 2004 1:50 PM

klktrk,

It’s likely that that information is stored in your keychain. To access that information you would go to Applications -> Utilities -> Keychain Access

You should be able to find it under the “Kind” header. Once found, you can delete or alter the key/password.

I don’t know for sure that is the case, but that’s my best guess.

16 Mark Allan remarks:
#16) On May 2, 2005 7:36 PM

Thank you so much for these instructions, they worked fantastically in Panther. Having now upgraded to Tiger (10.4) and Xcode 2.0, my projects with CVS no longer work. This is the error I get:

cvs [update aborted]: -t/-f wrappers not supported by this version of CVS

Any thoughts would be very gratefully received.

Thanks,
Mark

17 Justin Williams remarks:
#17) On May 2, 2005 8:56 PM

I haven’t tested this article in Tiger. Your mileage may vary.

Should I do a revised one for Tiger? Leave your thoughts in the comments.

18 Mark Allan remarks:
#18) On May 3, 2005 6:15 AM

I’m comfortable using it in my projects, but as I know precious little about setting up (or indeed fixing) CVS I would very much appreciate a slightly revised version for Tiger if you have time please.

Alternatively, how can I stop Xcode from submitting my changes with the -t or -f flags?

19 David Dolinar remarks:
#19) On May 4, 2005 3:31 PM

Tiger ships w/ a newer version of CVS v1.11.18. Panther used CVS v1.10. You can still use the ‘old cvs’ if you use the terminal by typing ‘ocvs’ instead of ‘cvs’, the latest version of CVL allows you to choose which command to use based on repository. Getting XCode to use the old version, I’m not sure.

I’m trying to figure out this whole wrappers deal (prompted by the same error message you’re getting). We have some files (.nibs) which need to be wrapped & I’m no sure how to do this w/o the -t & -f flags in the cvswrappers file.

If anyone knows anything please chime in or e-mail me!

20 David Dolinar remarks:
#20) On May 4, 2005 3:36 PM

mistyped my e-mail above…

21 MikeC remarks:
#21) On May 6, 2005 5:43 PM

Hmmm….I don’t see an obvious way to tag the project through SCM in XCode. I’ve been tagging my dev phases manually using ‘cvs tag ‘. Has anyone been able to apply tags through SCM?

22 Mark Allan remarks:
#22) On May 25, 2005 7:31 PM

If no-one else has managed anything better than this, then I’ll offer a hack-around which works.

Get info on your project and turn CVS off. Now, to the right of the SCM selection menu there’s an “edit” button, change what’s in there from “/usr/bin/cvs” to “/usr/bin/ocvs” (note the added letter ‘oh’, presumably for Old). Turn CVS back on and you’re up and running with the older version of CVS.

Not the most elegant of approaches, but it seems to work.

23 Olivier Palliere remarks:
#23) On July 17, 2005 2:38 PM

Hello,

Im trying this article to setup cvs on tiger, both the repository and the remote machine. I was able to get it working on the repository, using ocvs instead of cvs.

But when I try to co the project on the remote, I get the message about ocvs, even I use it:

joonze:~/Projects/1-CURRENT olivier$ ocvs co sunShield
cvs [checkout aborted]: -t/-f wrappers not supported by this version of CVS
A legacy version of cvs with -t/-f wrapper support is available as: /usr/bin/ocvs.

Is it possible to check out the project directly from Xcode, if the command line is not working?

24 Chris Stephens remarks:
#24) On July 26, 2005 2:00 AM

Hi folks,

Thanks for this article - very useful and easy to follow.

But I’m having a problem. Using Tiger/XCode 2.1 (and therefore ocvs as documented to support bundles) I can’t import all my files. When I run the “cvs import” commmand most of my files are listed with a preceding ‘N’ (for new) but one is preceded with ‘I’ (for what?) and is not imported.

The file is libeSellerateObjC.a - part of the eSellerate API.

And a whole framework is not imported either but this time the import lines are preced with ‘L’.

The funny thing is I can’t find this documented anywhere. I even have the printed version of the Karl Fogel book and have searched on the web…

Maybe I’m being stuipid here but can anyone help me - currently my project is effectively screwed?

Thanks in advance,

Chris

25 Chris Stephens remarks:
#25) On July 26, 2005 2:01 AM

Hi folks,

Thanks for this article - very useful and easy to follow.

But I’m having a problem. Using Tiger/XCode 2.1 (and therefore ocvs as documented to support bundles) I can’t import all my files. When I run the “cvs import” commmand most of my files are listed with a preceding ‘N’ (for new) but one is preceded with ‘I’ (for what?) and is not imported.

The file is libeSellerateObjC.a - part of the eSellerate API.

And a whole framework is not imported either but this time the import lines are preceded with ‘L’.

The funny thing is I can’t find this documented anywhere. I even have the printed version of the Karl Fogel book and have searched on the web…

Maybe I’m being stuipid here but can anyone help me - currently my project is effectively screwed?

Thanks in advance,

Chris

26 Chris Stephens remarks:
#26) On July 26, 2005 3:08 AM

OK, so I answered my own question - partly.

You can find out what all the ‘N’, ‘I’ and ‘L’ bits mean at http://www.cvsnt.org/manual/html/import.html.

And it seems the cvswrappers script on Tiger doesn’t recognise that a .a file is a binary so that needs to be added - just copy the line for .aiff files and remove the iff bit.

My framework isn’t being imported because it uses links (‘L’). Not sure how to fix that yet. Any ideas anyone?

Chris

27 Patrick LaRoche remarks:
#27) On August 17, 2005 11:56 AM

I also have the same problem as Olivier Palliere, where the wrappers work fine on the local machine using ocvs, but when connecting with a remote machine (Tiger, XCode 2.1) I still get the wrappers error, no matter which cvs version I use.

Any help would be great,
-P

28 Patrick LaRoche remarks:
#28) On August 18, 2005 9:40 AM

Solved my problem, you must force the client machine to use the server side ocvs instead of cvs. You can do this by (on the client machine):

export CVS_SERVER=/usr/bin/ocvs

(or whatever the path is to ocvs on the server macintosh)

29 Manav Bhatia remarks:
#29) On October 20, 2005 2:53 AM

Hi
Thanks for this article Justin. I am using Xcode 2.1 on OSX 10.4.2 and lately tried to get the CVS feature to work for remote CVS servers. However, whenever I ask for a ‘compare’ or ‘diff’ of a file from the local repository, I get the following error message from Xcode: “Internal Error: Uncaught Exception:
Invalid parameter not satisfying: aString != nil
Stack Backtrace:
The stack backtrace has been logged to the console.”
I get this message for all projects with a remote CVS server.
I use the cvs command instead of the ocvs.

I would be grateful if you could help me understand what is happening here.

Thanks
Manav