| Setup Local Repository |
To play in a sandbox, you can create local repository under your account,
/home/vlg/
|-cvsrepo/ <- Root of local CVS repository
| |-libfoo/ <- A project
| | |-README
| | ...
| |
| |-next-big-thing/ <- Another projectp
| | ...
|
|-libfoo/ <- Working copy checked out of CVS
|
|-rb1.0/ <- RB_1_0 branch of libfoo
|
|
First, create and initialize your local repository:
/home/vlg> mkdir cvsrepo /home/vlg> cd cvsrepo /home/vlg> cvs -d ~/cvsrepo init |
init command sets up the repository by creating ~/cvsrepo/CVSROOT/ directory that holds CVS housekeeping database files.
To access this repository, use -d ~/cvsrepo as repository locator.
| Setup Remote Repository |
Setup cvs root directory:
# cvs -d /usr/cvs init # cd /usr/cvs # chgrp -R cvs . # chmod ug+rw . CVSROOT |
When a remote CVS client uses the :pserver: method to connect to a repository, the client is actually connects to the port 2401. This port is the designated default port for a CVS server.
The CVS server is not actually waiting for connections on that port - instead the xinetd daemon answers the connection request and starts the CVS server to handle the actual data request. To accomplish this configuration, you have to configure xinetd daemon.
Create cvs file under
service cvspserver
{
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/bin/cvs
server_args = -f --allow-root=/home/cvs pserver
disable = no
}
|
Restart xinetd
To permit the remote access to the CVS repository, you have to set up special CVS passwords separate from the users' regular UNIX passwords, so that people can access the repository without compromising overall system security.
Make sure that the encrypted passwords are not the same as the user's actual login passwords. The passwords cross over the network in clear.
Create CVS password authentication file
% htpasswd -c passwd.file vlg Adding password for user vlg New password: MY_SECRET Re-type new password: MY_SECRET % cat passwd.file vlad:XXXXXXXXXXX:cvs vlg:XXXXXXXXXXX:cvs |
One thing to notice here is that the last parameter, cvs,
is not added by htpasswd. You have to put add it yourself
and them merge
[up]
| Setup user account |
Modify
export CVSROOT=:pserver:vlad@aurora:/home/cvs |
[up]
| Login into CVS |
Getting in and out of the remote CVS:
cvs -d :pserver:vlg@aurora:/home/cvs login cvs -d :pserver:vlg@aurora:/home/cvs logout |
[up]
| Add New Project To CVS |
Adding brand new project is done with "import" command:
/home/vlg> mkdir libfoo
/home/vlg> cd libfoo
/home/vlg/libfoo> vi README
create initial version
/home/vlg/libfoo> cvs import -m "Initial version" <Path/libfoo> vlg TRUNK
/home/vlg/libfoo> cd ..
/home/vlg> mv libfoo libfoo.0
|
<Path/libfoo> is how this module is going to be checked into CVS tree. The resultant path will be $CVSROOT/Path/libfoo. Having Path is not necessary.
Configuration file $CVSROOT/CVSROOT/modules allows to specify aliases for the project names, and control the way they are extracted.
# List all modules in CVS % cvs co -c libassa libassa libirina -d libirina extras/src/libirina % cd $CVSROOT/CVSROOT % cat modules libassa libassa libirina -d libirina extras/src/libirina |
Here, libassa is know as itself and can be checked out by its name accordingly. extras/src/libirina, however, is archived with long path to it, but can be checked out by its alias name, libirina. The option -d path controls where CVS files are going to be checked out locally.
[up]
| Get files from CVS |
% cvs checkout My_File_Name |
[up]
| Add New File to CVS |
% cvs add New_File_Name % cvs commit |
Binary files need to be checked into CVS a little bit differently (a CVS hack):
% cvs add -kb WordDocument.doc |
[up]
| Remove File From CVS |
% rm My_Old_File % cvs remove My_Old_File % cvs commit |
[up]
| Modify File |
% chmod 644 My_File % vi My_File ... make your changeschanges ... :wq % cvs commit |
When you want to update or merge a file, use the update command. This brings into your working directory the changes others have recently committed. If you have edited the file, and a newer revision is available, CVS will merge (or attempt to merge) all changes into your working directory. Conflicts may arise if you and someone else modified the same segment of the file. In this case, CVS will create a copy of the file with segment in question marked. You would need to modify the marked segment and the commit the change.
% cvs update -dP |
update command reports the modifications applied to files with letters leading each file that is updated or not:
[up]
| Tag Current Snapshot of CVS Thread |
# Tag the entire package % cvs tag rel_1_2_0 . # Tag a particular file % cvs tag rel_1_2_0 A_Particular_File |
The point of the tags is to record successive points on the branch where the developer considers the changes to be mergeable into the trunk. The tags name generally follow the form of [MODULE]_[MAJOR]_[MINOR]_[MICRO].
Running the
[up]
| Using Branches |
Use branch to create a release. Release can be then further patched in a release branch, while main development will continue in the trunk.
/home/vlg/libfoo> vi README
make changes and save ...
/home/vlg/libfoo> cvs commit -m ""
|
/home/vlg/libfoo> cvs tag Root-of-RB_1_0 |
[vlg@zorro]/vlg/libfoo> cvs status -v README
===================================================================
File: README Status: Up-to-date
Working revision: 1.3 Tue Jun 13 14:18:47 2006
Repository revision: 1.3 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
/home/vlg/libfoo> cvs rtag -b RB_1_0 libfoo /home/vlg/libfoo> cd ~ /home/vlg> |
===================================================================
File: README Status: Up-to-date
Working revision: 1.3 Tue Jun 13 14:18:47 2006
Repository revision: 1.3 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
RB_1_0 (branch: 1.3.2)
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
Logically, the branch tree now looks like this:
RB_1_0 branch
1.3.2 o-----------------
/
/
1.1.1 1.3/
TRUNK ==oo==================================
^^
||
|\____ RB_1_0 tag
|
\____Root-of-RB_1_0
|
/home/vlg> cvs co -r RB_1_0 -d rb1.0 libfoo /home/vlg> cd rb1.0 |
make your
changes here ----> RB_1_0 branch
1.3.2 o-------------------
/
/
1.3/
TRUNK ====oo=======================================
^^
||
|\____ RB_1_0 tag
|
\___ Root-of-RB_1_0
|
/home/vlg/rb1.0> vi README
make release-related changes ...
/home/vlg/rb1.0> cvs commit -m "Pre-release modifications"
/home/vlg/rb1.0> cvs update
|
===================================================================
File: README Status: Up-to-date
Working revision: 1.3.2.1 Tue Jun 13 14:29:16 2006
Repository revision: 1.3.2.1 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: RB_1_0 (branch: 1.3.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
RB_1_0 (branch: 1.3.2)
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
/home/vlg/rb1.0> cvs tag REL_1_0 |
1.3.2.1
v RB_1_0 (branch)
1.3.2 o--o-*----------------------
/ ^
/ |
/ \____ REL_1_0 (tag)
1.3/ Branch 1.1.1.1
TRUNK ===o=o=======================================
^ ^
| |
| \____ RB_1_0 (tag)
|
\____ Root-of-RB_1_0 (tag)
|
===================================================================
File: README Status: Up-to-date
Working revision: 1.3.2.1 Tue Jun 13 15:12:47 2006
Repository revision: 1.3.2.1 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: RB_1_0 (branch: 1.3.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
REL_1_0 (revision: 1.3.2.1)
RB_1_0 (branch: 1.3.2)
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
/home/joe/> cvs co -r REL_1_0 -d rel1.0 libfoo /home/joe/> cd rel1.0 /home/joe/rel1.0> build release code |
/home/vlg/rb1.0> cvs tag PRE_6969 /home/vlg/rb1.0> ... make changes and test them ... /home/vlg/rb1.0> cvs commit -m "First attempt to fix the bug" /home/vlg/rb1.0> ... make changes and test them ... /home/vlg/rb1.0> cvs commit -m "Fix for Bug #6969" /home/vlg/rb1.0> cvs tag POST_6969 |
/---------- PRE_6969 (1.3.2.1)
/ /------- fix 1, didn't work (1.3.2.2)
| / /---- fix 2, tested/ok (1.3.2.3)
| | / /-- POST_6969
| | | |
1.3.2 v v v v
RB_1_0 branch o---*----o--+--+--o-----------
/ \
/ \___ REL_1_0
1.3 /
TRUNK =====o=======================================
^
|
\____ RB_1_0 tag
|
===================================================================
File: README Status: Up-to-date
Working revision: 1.3.2.3 Tue Jun 13 15:27:10 2006
Repository revision: 1.3.2.3 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: RB_1_0 (branch: 1.3.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
POST_6969 (revision: 1.3.2.3)
PRE_6969 (revision: 1.3.2.1)
REL_1_0 (revision: 1.3.2.1)
RB_1_0 (branch: 1.3.2)
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
/home/vlg/rb1.0 > cd /home/vlg/libfoo /home/vlg/libfoo> cvs commit -m "" /home/vlg/libfoo> cvs update /home/vlg/libfoo> cvs update -j PRE_6969 -j POST_6969 /home/vlg/libfoo> ... rebuid and retest the main code /home/vlg/libfoo> cvs commit -m "Fix for bug #6969 from REL_1_0 branch" |
/---------- PRE_6969 (1.3.2.1)
| /-- POST_6969 (1.3.2.3)
| |
v v
RB_1_0 branch o---*----o--------o--------
/ \ \ cvs update -j POST_6969
/ \__ REL_1_0 \ puts changes back into the TRUNK
/ \
/ |
1.3 | V 1.4
TRUNK =====o=========================*=============
^ ^
| |
\____ RB_1_0 tag \__ Fix for bug #6969
merged back into trunk
|
===================================================================
File: README Status: Up-to-date
Working revision: 1.4 Tue Jun 13 15:36:23 2006
Repository revision: 1.4 /home/vlg/cvsrepo/libfoo/README,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
POST_6969 (revision: 1.3.2.3)
PRE_6969 (revision: 1.3.2.1)
REL_1_0 (revision: 1.3.2.1)
RB_1_0 (branch: 1.3.2)
Root-of-RB_1_0 (revision: 1.3)
TRUNK (revision: 1.1.1.1)
vlg (branch: 1.1.1)
-------------------------------------------------------------------
[up]
| Branch off an Existing Tag |
Sometimes you want to create an additional branch from a place different from the tip of the TRUNK. To do so, you need an existing tag in the TRUNK. In the example above, the Root-of-RB_1_0 tag can be used to create another branch. We call it RB_Experiment and it will be a sibling of RB_1_0 branch. With rtag, you can create a new branch in CVS from anywhere in your account.
/home/vlg> cvs -d$CVSROOT rtag -b -r Root-of-RB_1_0 RB_Experiment libfoo |
The -b switch creates a new branch. The -r EXISTING_TAG switch tells CVS where to insert new branch at. If omitted, the default is the tip of the TRUNK.
Now, you are ready to checkout and start coding in your new branch.
/home/vlg> cvs -d$CVSROOT co -r RB_Experiment -d libfoo-experiment libfoo |
The branch tree now looks like this:
o----------- RB_Experiment branch
/ 1.3.4
/
/o----------- RB_1_0 branch
// 1.3.2
//
1.3 //
TRUNK ====oo=======================================
^^
||
|\____ RB_1_0 tag
|
\___ Root-of-RB_1_0
|
[up]
| Get File Status |
% cvs status -v README |
Examine the output from above. Lines that being with "revision:" in the righthand column above are normal tags.
The ones that start with "branch: " is a branch tag (RB_1_0, vlg) -- it will always point to the latest version of the file on that branch! If you were to check out the code from the trunk TRUNK, you would get version 1.4 of README file. If you were to check out the code from RB_1_0 branch, you would get version 1.3.2.3 of the README file instead. Release REL_1_0 tag would get you 1.3.2.1 version.
Notice also the "Status:" of the file:
[up]
| Merge changes In and Out of the TRUNK |
Now and then a branch developer would need to merge the changes from the TRUNK back into his branch:
/home/cindy/dev-branch> cvs update -j HEAD |
Special HEAD tag is reserved just for this action. First, you would merge all the latest changes from the TRUNK, and then tag your branch after the merger to remember the action taken.
[up]
| Check Out Module Revision |
% cvs checkout -r rel1-2 My_Module_Name % cvs checkout -D '1 year ago' My_Module_Name |
[up]
| View Diff Between File Versions |
# diff between local and CVS' versions % cvs diff My_File # diff between versions 1.20 and 1.21 % cvs diff -r 1.20 -r 1.21 My_File |
[up]
| ViewCVS Front End |
ViewCVS lets you browse your CVS repository with a Web browser. At the heart of it is a CGI script that is executed by the Web browser to display CVS entries.
ViewCVS main website is
here.
Get, unpack, and install latest ViewCVS tar.gz.
Installation puts it into
/usr/local/viewcvs-VERSION/
directory.
Edit
... Development : /home/cvs ... main_title = Vlad's CVS Repository |
You would also have to configure your Web server to execute CGI scripts, and add users apache and nobody to the cvs group:
cvs::500:apache,nobody,vlad |
ViewCVS CGI scripts are installed in its installation tree /usr/local/viewcvs-VERSION/cgi/. You need to add this directory to the ScriptAlias list of /etc/httpd/conf/httpd.conf:
# File: /etc/httpd/conf/httpd.con # # ScriptAlias: This controls which directories contain server scripts. # ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" ScriptAlias /cvs/ "/usr/local/viewcvs-0.9.2/cgi/" |
Note: Make sure it is /cvs/, not /cgi-bin/ on the last line. Otherwise, it is not going to work at all!
Restart you Apache server and if you pointed your browser to URL http://host/cvs/viewcvs.cgi/, you would see your CVS!
[up]
| Make Nightly Tarball |
cvs -z3 -d:pserver:user@host:/home/cvs co Package | tar -cf Package-cvs.tar.gz - |
[up]
| Make a patch against CVS |
Let's say you have checked out a project from its CVS repository, and did some modifications to it to get it working with a new feature. To submit your patch to the project's developer, create a patch of your changes and submit it to the bug tracing system.
% cd libfoo/ % cvs diff -up > libfoo-mychanges.patch % gzip --best libfoo-mychanges.patch |
To merge a 'patch' into your source,
/home/vlg/libassa-trunk> patch -p[n] < [patch] |
where n is the number of leading components to strip from the path. This number is relative to where the patch was generated from.
If you need to reverse the patch, you can use the following command
/home/vlg/libassa-trunk> patch -R < [patch] |
[up]
| Use CVS With SSH |
In you ~/.profile set following environment variables:
export CVS_RSH="ssh" export CVSROOT=":ext:user@host:/path/to/cvsroot" |
[up]
| SourceForge CVS |
I keep my open-source projects on SourceForge. There is a small set of repetetive tasks I perform before each release.
% export CVSROOT=:pserver:anonymous@cvs-pserver.sourceforge.net:80/cvsroot/libassa % cvs -z3 -d$CVSROOT co libassa % cvs -z3 -d$CVSROOT co libassa-manual |
[up]
| Useful Links |
[up]
| Copyright © 2005-2006 Vladislav Grinchenko |
| Last updated: Jun 12, 2006 |