<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sect2 SYSTEM "../../../dtd/dblite.dtd">

<sect2 lang="en" id="git-cvsimport(1)">
    <title>git-cvsimport(1)</title>
    <date>2024-07-02</date>
<revhistory><revision><date>2024-07-02</date></revision></revhistory>
<indexterm>
<primary>git-cvsimport(1)</primary>
</indexterm>
<simplesect id="git-cvsimport(1)__name">
<title>NAME</title>
<simpara>git-cvsimport - Salvage your data out of another SCM people love to hate</simpara>
</simplesect>
<simplesect id="git-cvsimport(1)__synopsis">
<title>SYNOPSIS</title>
<blockquote>
<literallayout><emphasis>git cvsimport</emphasis> [-o &lt;branch-for-HEAD&gt;] [-h] [-v] [-d &lt;CVSROOT&gt;]
              [-A &lt;author-conv-file&gt;] [-p &lt;options-for-cvsps&gt;] [-P &lt;file&gt;]
              [-C &lt;git-repository&gt;] [-z &lt;fuzz&gt;] [-i] [-k] [-u] [-s &lt;subst&gt;]
              [-a] [-m] [-M &lt;regex&gt;] [-S &lt;regex&gt;] [-L &lt;commit-limit&gt;]
              [-r &lt;remote&gt;] [-R] [&lt;CVS-module&gt;]</literallayout>
</blockquote>
</simplesect>
<simplesect id="git-cvsimport(1)__description">
<title>DESCRIPTION</title>
<simpara><emphasis role="strong">WARNING:</emphasis> <emphasis>git cvsimport</emphasis> uses cvsps version 2, which is considered
deprecated; it does not work with cvsps version 3 and later.  If you are
performing a one-shot import of a CVS repository consider using
<ulink url="http://cvs2svn.tigris.org/cvs2git.html">cvs2git</ulink> or
<ulink url="https://gitlab.com/esr/cvs-fast-export">cvs-fast-export</ulink>.</simpara>
<simpara>Imports a CVS repository into Git. It will either create a new
repository, or incrementally import into an existing one.</simpara>
<simpara>Splitting the CVS log into patch sets is done by <emphasis>cvsps</emphasis>.
At least version 2.1 is required.</simpara>
<simpara><emphasis role="strong">WARNING:</emphasis> for certain situations the import leads to incorrect results.
Please see the section <link linkend="git-cvsimport(1)_issues">ISSUES</link> for further reference.</simpara>
<simpara>You should <emphasis role="strong">never</emphasis> do any work of your own on the branches that are
created by <emphasis>git cvsimport</emphasis>.  By default initial import will create and populate a
"master" branch from the CVS repository's main branch which you're free
to work with; after that, you need to <emphasis>git merge</emphasis> incremental imports, or
any CVS branches, yourself.  It is advisable to specify a named remote via
-r to separate and protect the incoming branches.</simpara>
<simpara>If you intend to set up a shared public repository that all developers can
read/write, or if you want to use <xref linkend="git-cvsserver(1)" />, then you
probably want to make a bare clone of the imported repository,
and use the clone as the shared repository.
See <xref linkend="gitcvs-migration(7)" />.</simpara>
</simplesect>
<simplesect id="git-cvsimport(1)__options">
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>
-v
</term>
<listitem>
<simpara>
        Verbosity: let <emphasis>cvsimport</emphasis> report what it is doing.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-d &lt;CVSROOT&gt;
</term>
<listitem>
<simpara>
        The root of the CVS archive. May be local (a simple path) or remote;
        currently, only the :local:, :ext: and :pserver: access methods
        are supported. If not given, <emphasis>git cvsimport</emphasis> will try to read it
        from <emphasis>CVS/Root</emphasis>. If no such file exists, it checks for the
        <emphasis>CVSROOT</emphasis> environment variable.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
&lt;CVS-module&gt;
</term>
<listitem>
<simpara>
        The CVS module you want to import. Relative to &lt;CVSROOT&gt;.
        If not given, <emphasis>git cvsimport</emphasis> tries to read it from
        <emphasis>CVS/Repository</emphasis>.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-C &lt;target-dir&gt;
</term>
<listitem>
<simpara>
        The Git repository to import to.  If the directory doesn't
        exist, it will be created.  Default is the current directory.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-r &lt;remote&gt;
</term>
<listitem>
<simpara>
        The Git remote to import this CVS repository into.
        Moves all CVS branches into remotes/&lt;remote&gt;/&lt;branch&gt;
        akin to the way <emphasis>git clone</emphasis> uses <emphasis>origin</emphasis> by default.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-o &lt;branch-for-HEAD&gt;
</term>
<listitem>
<simpara>
        When no remote is specified (via -r) the <emphasis>HEAD</emphasis> branch
        from CVS is imported to the <emphasis>origin</emphasis> branch within the Git
        repository, as <emphasis>HEAD</emphasis> already has a special meaning for Git.
        When a remote is specified the <emphasis>HEAD</emphasis> branch is named
        remotes/&lt;remote&gt;/master mirroring <emphasis>git clone</emphasis> behaviour.
        Use this option if you want to import into a different
        branch.
</simpara>
<simpara>Use <emphasis>-o master</emphasis> for continuing an import that was initially done by
the old cvs2git tool.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-i
</term>
<listitem>
<simpara>
        Import-only: don't perform a checkout after importing.  This option
        ensures the working directory and index remain untouched and will
        not create them if they do not exist.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-k
</term>
<listitem>
<simpara>
        Kill keywords: will extract files with <emphasis>-kk</emphasis> from the CVS archive
        to avoid noisy changesets. Highly recommended, but off by default
        to preserve compatibility with early imported trees.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-u
</term>
<listitem>
<simpara>
        Convert underscores in tag and branch names to dots.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-s &lt;subst&gt;
</term>
<listitem>
<simpara>
        Substitute the character "/" in branch names with &lt;subst&gt;
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-p &lt;options-for-cvsps&gt;
</term>
<listitem>
<simpara>
        Additional options for cvsps.
        The options <emphasis>-u</emphasis> and <emphasis>-A</emphasis> are implicit and should not be used here.
</simpara>
<simpara>If you need to pass multiple options, separate them with a comma.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-z &lt;fuzz&gt;
</term>
<listitem>
<simpara>
        Pass the timestamp fuzz factor to cvsps, in seconds. If unset,
        cvsps defaults to 300s.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-P &lt;cvsps-output-file&gt;
</term>
<listitem>
<simpara>
        Instead of calling cvsps, read the provided cvsps output file. Useful
        for debugging or when cvsps is being handled outside cvsimport.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-m
</term>
<listitem>
<simpara>
        Attempt to detect merges based on the commit message. This option
        will enable default regexes that try to capture the source
        branch name from the commit message.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-M &lt;regex&gt;
</term>
<listitem>
<simpara>
        Attempt to detect merges based on the commit message with a custom
        regex. It can be used with <emphasis>-m</emphasis> to enable the default regexes
        as well. You must escape forward slashes.
</simpara>
<simpara>The regex must capture the source branch name in $1.</simpara>
<simpara>This option can be used several times to provide several detection regexes.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-S &lt;regex&gt;
</term>
<listitem>
<simpara>
        Skip paths matching the regex.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-a
</term>
<listitem>
<simpara>
        Import all commits, including recent ones. cvsimport by default
        skips commits that have a timestamp less than 10 minutes ago.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-L &lt;limit&gt;
</term>
<listitem>
<simpara>
        Limit the number of commits imported. Workaround for cases where
        cvsimport leaks memory.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-A &lt;author-conv-file&gt;
</term>
<listitem>
<simpara>
        CVS by default uses the Unix username when writing its
        commit logs. Using this option and an author-conv-file
        maps the name recorded in CVS to author name, e-mail and
        optional time zone:
</simpara>
<screen>        exon=Andreas Ericsson &lt;ae@op5.se&gt;
        spawn=Simon Pawn &lt;spawn@frog-pond.org&gt; America/Chicago</screen>
<simpara><emphasis>git cvsimport</emphasis> will make it appear as those authors had
their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
all along.  If a time zone is specified, GIT_AUTHOR_DATE will
have the corresponding offset applied.</simpara>
<simpara>For convenience, this data is saved to <emphasis>$GIT_DIR/cvs-authors</emphasis>
each time the <emphasis>-A</emphasis> option is provided and read from that same
file each time <emphasis>git cvsimport</emphasis> is run.</simpara>
<simpara>It is not recommended to use this feature if you intend to
export changes back to CVS again later with
<emphasis>git cvsexportcommit</emphasis>.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-R
</term>
<listitem>
<simpara>
        Generate a <emphasis>$GIT_DIR/cvs-revisions</emphasis> file containing a mapping from CVS
        revision numbers to newly-created Git commit IDs.  The generated file
        will contain one line for each (filename, revision) pair imported;
        each line will look like
</simpara>
<screen>src/widget.c 1.1 1d862f173cdc7325b6fa6d2ae1cfd61fd1b512b7</screen>
<simpara>The revision data is appended to the file if it already exists, for use when
doing incremental imports.</simpara>
<simpara>This option may be useful if you have CVS revision numbers stored in commit
messages, bug-tracking systems, email archives, and the like.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>
-h
</term>
<listitem>
<simpara>
        Print a short usage message and exit.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</simplesect>
<simplesect id="git-cvsimport(1)__output">
<title>OUTPUT</title>
<simpara>If <emphasis>-v</emphasis> is specified, the script reports what it is doing.</simpara>
<simpara>Otherwise, success is indicated the Unix way, i.e. by simply exiting with
a zero exit status.</simpara>
</simplesect>
<simplesect id="git-cvsimport(1)_issues">
<title>ISSUES</title>
<simpara>Problems related to timestamps:</simpara>
<itemizedlist>
<listitem>
<simpara>
If timestamps of commits in the CVS repository are not stable enough
   to be used for ordering commits changes may show up in the wrong
   order.
</simpara>
</listitem>
<listitem>
<simpara>
If any files were ever "cvs import"ed more than once (e.g., import of
   more than one vendor release) the HEAD contains the wrong content.
</simpara>
</listitem>
<listitem>
<simpara>
If the timestamp order of different files cross the revision order
   within the commit matching time window the order of commits may be
   wrong.
</simpara>
</listitem>
</itemizedlist>
<simpara>Problems related to branches:</simpara>
<itemizedlist>
<listitem>
<simpara>
Branches on which no commits have been made are not imported.
</simpara>
</listitem>
<listitem>
<simpara>
All files from the branching point are added to a branch even if
   never added in CVS.
</simpara>
</listitem>
<listitem>
<simpara>
This applies to files added to the source branch <emphasis role="strong">after</emphasis> a daughter
   branch was created: if previously no commit was made on the daughter
   branch they will erroneously be added to the daughter branch in git.
</simpara>
</listitem>
</itemizedlist>
<simpara>Problems related to tags:</simpara>
<itemizedlist>
<listitem>
<simpara>
Multiple tags on the same revision are not imported.
</simpara>
</listitem>
</itemizedlist>
<simpara>If you suspect that any of these issues may apply to the repository you
want to import, consider using cvs2git:</simpara>
<itemizedlist>
<listitem>
<simpara>
cvs2git (part of cvs2svn), <emphasis>https://subversion.apache.org/</emphasis>
</simpara>
</listitem>
</itemizedlist>
</simplesect>
<simplesect id="git-cvsimport(1)__git">
<title>GIT</title>
<simpara>Part of the <xref linkend="git(1)" /> suite</simpara>
</simplesect>
</sect2>
