A Crash Course in CVS 19 November 2003 Joe Vornehm Northwestern University ECE Department Overview • • • • • • The need for version control Version control basics CVS basics: adding, updating, committing... Controlling the project Things that don’t work well Q&A Assumptions • Basic familiarity with Unix shells – GUI tools also available • For “Unix on Windows:” www.cygwin.com • For more info: www.cvshome.org • This presentation: http://www.ece.northwestern.edu/~jev283/ talks/cvs/ The Need for Version Control • Tracking changes during development – Seeing how, when things changed – “The ‘Oops’ factor” • Coordinating among multiple developers • Access control (not CVS) • Solution: Keep a history of each file in a central location called the “repository” Version Control Systems • Big “Repository in the Sky” • Local copies of files in “working directory” – Develop program in working directory – Copy files to/from repository—called “checking in/out” or “committing/updating” Repository Alice’s working directory Bob’s working directory Interacting with CVS • cvs command – GUIs also available – CVS interface built into editors, MATLAB, etc. • CVSROOT environment variable specifies location of CVS repository – Can be local directory, network disk, CVS “pserver,” rsh/ssh tunnel – Can also use “cvs -d” CVS Commands • • • • cvs global-opts command command-opts cvs --help-commands, cvs -H command cvs --help-options (not for beginners) Examples: – cvs add hello.c – cvs add -m “Created hello.c” hello.c – cvs -d $MY_CVSROOT add -m “Created hello.c” hello.c CVS Commands (concl.) • Most CVS commands accept a filename, many filenames, or no filename to mean the current directory (and -R to recurse below the current directory) One Important Global Option • cvs -n command … causes CVS to execute the command without changing any files on disk (or in the repository) – Good for seeing what something will do before you try it – Certain behaviors are different with -n, so you may get strange errors that go away when you don’t use -n Getting Started • Easiest way: import an existing project, then create a new working directory • Make a repository: – mkdir /project/cvsroot – export CVSROOT=/project/cvsroot • Probably want this in .profile or .cshrc – cvs init Getting Started (cont.) • Import original source directory – cd /project/myproj – cvs import myproj mygroup start • myproj is the name of the CVS “module” • mygroup is some tag indicating where the sources came from (not used very much) • start is some tag indicating that this is the very first import of this project into CVS Getting Started (concl.) • Create a local working directory – cd ~/work – cvs checkout myproj • Gets a clean copy of myproj source code, puts it in directory myproj – cd myproj • Start developing! The Daily Grind • cvs commit, update, and add make up the vast majority of day-to-day CVS usage • cvs commit: Take changes made to working directory, commit them to CVS repository • cvs update: Get latest versions from CVS repository, update working directory • cvs add: Add a file from the working directory to the repository cvs commit • Make changes to a file, then commit the file using cvs commit filename – CVS prompts for a “log message,” something short and descriptive of changes, like, “Changed frobnitz operator to support multiple inheritance.” – Alt.: specify message using cvs commit -m msg • “cvs commit” with no filename commits all changed files in current directory cvs update • cvs update filename updates a file in the working directory so it matches the latest version in the repository • “cvs update” with no filename updates all changed files in current directory • CVS actually updates files by merging version-to-version changes with the working directory file… more later. cvs add • cvs add filename tells CVS to add a file to the repository during the next commit operation • cvs commit filename (or cvs commit) actually adds the file… same syntax as before. Status information • cvs log filename gives a history of all commit log messages for a particular file • cvs status filename gives status information about a particular file (version number, whether it needs an update or a commit, etc.) • cvs history gives history information about repository accesses Useful Commands • cvs diff filename compares a local file to a repository version, compares two versions, etc. • cvs update -p filename prints the updated file to the screen without changing the file on disk… useful for pipe commands CVS Keywords • CVS generally does not independently change the contents of files you commit or update • Keywords are an exception: $Id$, $Revision$, $Log$, etc. • CVS updates these strings with the appropriate information at each revision CVS Keywords (cont.) • Example: /* hello.c -- Guess what it does. */ #include <stdio.h> /* $Revision$ */ int main(int argc, char **argv) etc. CVS Keywords (concl.) • After check-in, the file reads: /* hello.c -- Guess what it does. */ #include <stdio.h> /* $Revision: 1.1$ */ int main(int argc, char **argv) etc. Adding another person • Ideal development cycle: – Alice works on functions.c, Bob works on main.c – Alice makes a change to functions.c, commits – Alice: “Bob, I added that thingy to functions.c.” – Bob: “OK.” – Bob runs cvs update functions.c (or just cvs update) and continues developing main.c Adding Another Person (cont.) • More realistic development cycle: – – – – – Alice is working on sum() in functions.c Bob is working on product() in functions.c Alice finishes sum() and commits functions.c Bob finishes product() and tries to commit CVS refuses, because it knows Bob is working on an old version of functions.c Adding Another Person (cont.) • What is Bob to do? – Bob runs cvs update functions.c – If Bob is lucky, he and Alice haven’t changed the same lines anywhere • CVS merges Alice’s changes with Bob’s in Bob’s copy of functions.c • Now Bob can commit his copy of functions.c with both his changes and Alice’s • …and Bob should tell Alice that he committed functions.c again! Adding Another Person (cont.) • What if Alice’s and Bob’s changes conflict? – If Bob is unlucky, he and Alice have changed some of the same lines in different ways – cvs update: In the conflicting areas, CVS puts both sets of changes into Bob’s copy of functions.c, set off by angle brackets – Bob has to merge the changes manually (typically deciding whether to keep his changes or Alice’s) and then commit the file. Adding Another Person (cont.) • Other ways to handle conflicting updates: – Alice and Bob can have a meeting to discuss which changes Bob should make – Bob can postpone the merge and just continue development with his own functions.c (without Alice’s changes) – Bob can overwrite his functions.c with the repository copy (that has Alice’s changes but not his) Adding Another Person (concl.) • One developer: never (rarely) any conflicts • A few developers (2-20): occasional conflicts – Either each piece of code is one person’s responsibility, or developers are working together anyway • Many developers: conflicts arise – Need more than just CVS to resolve issues Tag! You’re It • Sometimes you want a snapshot of the project state • Symbolic tags are a way to do that – One tag means “the version of each file that was current when this tag was created” – Good for external releases, forks, big decision points, experimenting • cvs tag tagname or cvs tag tagname files Working with Old Versions • Most CVS commands (commit, update, diff) accept the -r revision flag to deal with a specific version instead of the most recent version – Example: cvs update -r 1.3 functions.c will go back to version 1.3 of functions.c • But beware: this creates a “sticky tag” that may bite you later… Sticky Tags • Sticky tags are CVS attributes that “stick” to a file across commit/update cycles • Most common sticky tag is revision number – After cvs update -r revision filename, future updates of filename will still “update” it to version revision, not the current version • To undo: cvs update -A filename • Note: Regular tags (cvs tag) are sticky, too Branches • Sometimes, development needs to go down two different paths simultaneously (e.g., experimental features) • Tag the project, but make the tag a “branch tag” using cvs tag -b • Tags are sticky; CVS will know to commit to the branch instead of to the main development line Branches (concl.) • Branches can be merged or brought into sync • Branches can cause some headaches if not used properly • It’s often easier to develop a branch in a separate working directory from your main working directory Advanced Topics • Editing repository files or CVS-directory directly (text editor, format is simple) • Writing scripts that run every time something happens to the repository (commit, update, etc.) • Unix, Windows, Cygwin, end-of-line compatibility Some Things Don’t Work (Well) • • • • Deleting files: works but with artifacts Renaming files: not easy but possible Renaming directories: good luck! Version numbers can be confusing (1.1 vs. 1.1.1.1) • Can’t use CVS for access control (except maybe via repository scripts) Other Version Control Solutions • • • • • • subversions (GNU) RCS (GNU)—older, not as flexible SCCS (vendors), PVCS Clearcase, MS Visual SourceSafe Try http://www.gnu.org/directory/ Look for CVS add-ons (e.g. GUIs) at http://www.cvshome.org/