lcvs - Add a global log file and unique tags to cvs and other useful tools


lcvs [cvs-option...] cvs-command [cvs-command-option...]


lcvs is a wrapper around cvs providing

It is used as front end to cvs but also needs special arrangment in the administrative files (see "PREREQUISITES").

Because lcvs is a wrapper, which changes some commands while passing through others, the easiest way to use it is to use it in every place cvs would have been used.

Note: This manual assumes you have some knowledge about cvs and its concepts.


All options are those used by the original cvs command. Normally only cvs-options are parsed to find the cvs-command while other options are not even looked at.

The exception from the rule is the option -H without a cvs-command. This produces this manual page just as an invalid option does. Use --help to get help from cvs.

When options are concerned some cvs commands overlayed by lcvs are more restrictive than the original commands. This is described with the overlayed command.

A cvs-option of -s generally specifies a variable for expansion in an administrative file on the server holding the repository. For such variables the prefix LCVS_ is reserved for internal use by lcvs. See "LOGINFO FORWARDING" for uses of these reserved variables. All these variables may be also set in the environemt but the values given by options supersede these.


The following commands are overlayed by lcvs. Some of them restrict the possible options, and some of them use the parameters in special ways.


The commit command is central to all functions of lcvs.

The following restrictions or modifications to the original command apply.

The following features are added.


The import command is important for some functions of lcvs. Actually it has three different operation modes.

The following restrictions or modifications to the original command apply.

In addition all the additional features of commit are done. However, when importing a new module or to a new vendor branch the log file is not maintained.


The add command is important only because adding a directory leaves a trace in a log file.

No restrictions or modifications to the original command apply.


The following commands are not cvs commands but added to lcvs. All such commands start with a capital letter, so it is easy to distinguish them from original cvs commands.



lcvs [cvs-option...] Changed [-l] [-F log-file]


This command gives a quick overview about the change state of the current tree. Basically it reformats the output of a status focusing on the important information.

After that it outputs a log file if one is present.

A synonym for this command is Chgd.

The following options are supported.


Look in local directory only.

-F log-file

This option gives the name of the log file to output. It defaults to log. If the log file is not present this is silently ignored.


Be terse. Do not add the message and output only file names of changed files.



lcvs [cvs-option...] Increment [-t] [-F log-file] [-m log-message]


This command increments the major number in the symbolic tag in tag.log and/or the most significant revision number in the RCS files.

This operation is useful to create a new most significant revision number to base a set of new vendor branches on.

A synonym for this command is Inc.

The following options are supported.

-F log-file
-m message

These options are the same as for commit. Also if none of them present default to -F log and this is removed.


Normally both the major number in the symbolic tag in tag.log as well as the most significant revision number in the RCS file are incremented. This option increments only the major number in the symbolic tag. However, use of this option is not recommended. Instead the most significant revision number should be the same as the major version number in the symbolic tag.

Note: The option to increment the most significant revision number only is left out consciously. This should not be done. If it us ultimately needed for some reasons you can by using lcvs commit -r revision.

The following restrictions apply.



lcvs [cvs-option...] Join [source-branch]


Joins the latest changes made on branch source-branch to the current working directory which must be the top level directory of a checked out version of the target branch of the same module. If source-branch is not given defaults to the trunk.

Assume you have two branches A and B and from time to time you want to integrate the changes made on source branch A into target branch B. This is difficult by pure cvs. This is where Join helps.

Join does two things:

If a Join has not been committed yet - i.e. if there is a tag.join - then Join refuses to work. commit the pending Join first.

It is difficult to recognize a situation where the target branch has just been created but no commit has been done to it. Do not use Join in such situations.



lcvs [cvs-option...] List [-l] [-f]


This command lists all files in current tree.

A synonym for this command is Ls.

The following options are supported.


Normally the files global.log and tag.log created by lcvs are not included in the output. If this option is given, the files are treated as ordinary files.


Look in local directory only.



lcvs [cvs-option...] Log [-a] [-d] [-f] [-v] [-B] [-D] [-M] [-T]


This command outputs the contents global.log in various ways.

If there is an argument this is opened as a file for reading. If no argument is given it defaults to global.log.

The following options are supported.


Include author.


Include date.


Include files.


Include RCS version.


Exclude branch.


Exclude directories.


Exclude log message.


Exclude tag.



lcvs [cvs-option...] Undo [-f]

lcvs [cvs-option...] Undo -p

lcvs [cvs-option...] Undo -r


This command undoes the changes made to files in the current working directory reverting all changed files back to there unchanged version which is typically the one noted in tag.log. The changed files are saved by renaming them using the extension .redo.

This does not work for added and removed files. Local additions and removals must be reverted by hand. This also does not work if cvs reports an unresolved conflict. In all these cases the files causing trouble are output.

The following options are supported.


Instead of renaming the changed files remove them from the file system.

Use with care. Any changes are really lost if this option is used.


Purges all .redo files created by a previous run. This is meant for cleaning up and should be done if it is clear that the changes are no longer needed.

This is a security feature so no changes are removed by accident.


Instead of undoing redo the changes by renaming the changed files by removing the extension .redo.

Does work only until -p is used.


lcvs is usable with the more modern arrangements of remote repositories - i.e. the repository you are working with is not available in the file system of the computer you are issuing the lcvs command. The problem is that the information for a commit and similar sub commands is generated on the repository server and thus can not be used locally without special arrangment. However, lcvs needs this information locally to put it in the global.log file.

Administrative file loginfo

lcvs tackles this problem by opening a port on the local (client) machine. On this port the information generated on the repository server by the administrative file loginfo is expected. To forward the information from the server loginfo should contain the line:

        ALL     perl -MIO::Socket -e 'IO::Socket::INET->new("'${=LCVS_HOST}':'${=LCVS_PORT}'")->print(join("\n", scalar(@ARGV), @ARGV, ""), <STDIN>)' -- -d "`date`" -u ${USER} %s

This forwards the information from a server host holding the repository to the client host currently executing lcvs. If this fails on the server you will see an error message just after the messages about the checkin of a file.

Of course you may choose something different than ALL. Consult the CVS documentation for details.

See "loginfo options" for a description of the options you may give. See "LCVS_HOST and LCVS_PORT" and "Standard scenarios" for a description on how to get the information from the server to the client machine.

loginfo options

There are several options you may add to the perl call noted above. These are used to transfer more information from the server environment to the client. Please note that you must have -- in the loginfo line because otherwise options are interpreted by perl.

The following options are supported:

-d "`date`"

This transfers the date on the server to the client. As shown in the synopsis the quoted output of the date command should be used.

Using this option has the advantage to have a single time zone and clock for all users committing to the repository.

Defaults to the date on the client.

-m mail-address

This gives a mail address to which the information added to global.log is sent to.

Note: This is more useful than other solutions sending mail directly by loginfo because lcvs gathers all the messages from a commit of a module to form a reasonable message where other solutions send a message for each committed directory.

If this option is used the user executing lcvs must have the command mail available.

Defaults to nothing so by default no mail is sent.

This option may be given multiple to send mail to more than one address.

-u ${USER}

This transfers the user name on the server to the client. As shown in the synopsis the internal cvs variable ${USER} should be used.

Defaults to the user name of the user calling lcvs on the client.


As you may have noted in the line above the script called on the repository server gets the information about wich port on which host to connect to through the cvs variables LCVS_HOST and LCVS_PORT. These variables can be defined on the lcvs command line by using

        B<-s> C<LCVS_>I<...>C<=>I<...>

to set host and port and they may be set in the environment. However, this is usually not necessary because lcvs figures out good defaults. For some cvs sub commands they are always used internally to communicate the host and port lcvs is expecting the loginfo information.

When allocating the port to listen on lcvs checks the availability of the given or a built-in default port. If this port is not available the next one is tried until a free one is found. The port found is used for setting LCVS_PORT in the cvs call.

Standard scenarios

There are several cases you may consider for setting up things so everything works as it should. You always need to update loginfo as noted above.


The tags automatically maintained by lcvs consist of these parts.

The tag is held in the file tag.log and noted in the log file global.log on each commit.


All environment variables starting with LCVS_ can be superseded by -s LCVS_... options.


If this is set to /the/path/to/lcvs then lcvs is called to make the connection to the server host holding the repository. In this case LCVS_RSH is used.

See "LOGINFO FORWARDING" for further infomation.


The analogon to CVS_RSH. It's value should be the one you would use for CVS_RSH when not using lcvs.

It is used when a ssh call is rerouted through lcvs. The value of this variable may contain options separated by white space. -v might be useful to debug the connection to the repository server.

See "LOGINFO FORWARDING" for further infomation.


See "LOGINFO FORWARDING" for further infomation.



The global log file for a tree located in the top level directory of the tree. This is created by the overlayed import command. If it is not present no logging takes place. This should be controlled by cvs so it is checked out with the remaining files.

The log file grows at the beginning so the latest information is always at the beginning of the file.


The global file containing the latest tag on a single line. See "TAGS" for a description of the format. This is created by the overlayed import command. If it is not present no tagging takes place. This should be controlled by cvs so it is checked out with the remaining files.

This file may be used by other software to easily fetch the current tag of a tree.


This file is created by the Join sub command and it used by a following commit. It contains the latest tag from the source tree at the time the last Join took place.


In some places used as a default file containing the log message for the current / next commit.


A suite of scripts implementing the concept of lcvs started in 1993. These scripts hooked into several cvs administrative files.

In 1998 this has been replaced by this Perl script wrapped around cvs making things much easier. At the same time some minor changes took place in the concept.

In 2002 remote repositories have been made working. This simplified the code and the program logic considerably.

Because of this long history the code of lcvs is not as clean as it could be. But then - it works ;-) .


There may be smaller bugs and flaws in the concept. In particular the operation without global.log and/or tag.log is not tested. However, I'm using lcvs and it's predesseors for many years now and it works fine.

The following is actually more a ToDo list.


Because this is a Perl program, Perl (>= V5.005) must be installed.

Before using lcvs you should change the CVS administrative file loginfo according to the information in "LOGINFO FORWARDING".

To put a tree already existing in the cvs repository under lcvs control add a global.log and tag.log file at the top level. Initialize tag.log according to "TAGS".




Stefan Merten <>


This program is licensed under the terms of the GPL. See