<chapter id="goals">
  <title>Goals &mdash; The goals of the Subversion project</title>

  <simplesect>
    <para>The goal of the Subversion project is to write a version control
      system that takes over CVS's current and future user base
      <footnote><para>If you're not familiar with CVS or its shortcomings, then
          skip to <xref linkend="model"/></para></footnote>. The first release
      has all the major features of CVS, plus certain new features that CVS
      users often wish they had.  In general, Subversion works like CVS, except
      where there's a compelling reason to be different.</para>

    <para>So what does Subversion have that CVS doesn't?</para>

    <itemizedlist mark="bullet">
      <listitem><para>It versions directories, file-metadata, renames, copies
          and removals/resurrections.  In other words, Subversion records the
          changes users make to directory trees, not just changes to file
          contents.</para></listitem>

      <listitem><para>Tagging and branching are constant-time and
          constant-space.</para></listitem>

      <listitem><para>It is natively client-server, hence much more
          maintainable than CVS. (In CVS, the client-server protocol was added
          as an afterthought. This means that most new features have to be
          implemented twice, or at least more than once: code for the local
          case, and code for the client-server case.)</para></listitem>

      <listitem><para>The repository is organized efficiently and
          comprehensibly.  (Without going into too much detail, let's just say
          that CVS's repository structure is showing its
          age.)</para></listitem>

      <listitem><para>Commits are atomic.  Each commit results in a single
          revision number, which refers to the state of the entire tree.  Files
          no longer havetheir own revision numbers.</para></listitem>

      <listitem><para>The locking scheme is only as strict as absolutely
          necessary. Reads are never locked, and writes lock only the files
          being written, for only as long as needed.</para></listitem>

      <listitem><para>It has internationalization support.</para></listitem>

      <listitem><para>It handles binary files gracefully (experience has shown
          that CVS's binary file handling is prone to user
          error).</para></listitem>

      <listitem><para>It takes advantage of the Net's experience with CVS by
          choosing better default behaviors for certain
          situations.</para></listitem>
    </itemizedlist>

    <para>Some of these advantages are clear and require no further discussion.
      Others are not so obvious, and are explained in greater detail
      below.</para>
  </simplesect>

  <sect1 id="goals.rename-remove-resurrect">
    <title>Rename/removal/resurrection support</title>

    <para>Full rename support means you can trace through ancestry by name
      <emphasis>or</emphasis> by entity.  For example, if you say "Give me
      revision 12 of foo.c", do you mean revision 12 of the file whose name is
      <emphasis>now</emphasis> foo.c (but perhaps it was named bar.c back at
      revision 12), or the file whose name was foo.c in revision 12 (perhaps
      that file no longer exists, or has a different name now)?  In Subversion,
      both interpretations are available to the user.</para>

    <para>(Note:  we've not yet implemented this, but it wouldn't be too hard.
      People are advocating switches to 'svn log' that cause history to be
      traced backwards either by entity or by path.)</para>
  </sect1>

  <sect1 id="goals.textbinary">
    <title>Text vs binary issues</title>

    <para>Historically, binary files have been problematic in CVS for two
      unrelated reasons: keyword expansion, and line-end conversion.</para>

    <itemizedlist mark="bullet">
      <listitem><para><firstterm>Keyword expansion</firstterm> is when CVS
          expands "$Revision$" into "$Revision: 1.1 $", for example.  There
          are a number of keywords in CVS: "$Author: sussman $", "$Date:
          2001/06/04 22:00:52 $", and so on.</para></listitem>
      <listitem><para><firstterm>Line-end conversion</firstterm> is when CVS
          gives plaintext files theappropriate line-ending conventions for the
          working copy's platform. For example, Unix working copies use LF, but
          Windows working copies use CRLF.  (Like CVS, the Subversion
          repository stores text files in Unix LF format).</para></listitem>
    </itemizedlist>

    <para>Both keyword substitution and line-end conversion are sensible only
      for plain text files.  CVS only recognizes two file types anyway:
      plaintext and binary.  And CVS assumes files are plain text unless you
      tell it otherwise.</para>

    <para>Subversion recognizes the same two types.  The question is, how does
      it determine a file's type?  Experience with CVS suggests that assuming
      text unless told otherwise is a losing strategy &ndash; people frequently
      forget to mark images and other opaque formats as binary, then later they
      wonder why CVS mangled their data.  So Subversion will not mangle data:
      when moving over the network, or when being stored in the repository, it
      treats all files as binary.  In the working copy, a tweakable meta-data
      property indicates whether to treat the file as text or binary for
      purposes of whether or not to allow contextual merging during
      updates.</para>

    <para>Users can turn line-end conversion on or off per file by tweaking
      meta-data.  Files do <emphasis>not</emphasis> undergo keyword
      substitution by default, on the theory that if someone wants substitution
      and isn't getting it, they'll look in the manual; but if they are getting
      it and didn't want it, they might just be confused and not know what to
      do.  Users can turn substitution on or off per file.</para>

    <para>Both of these changes are done on the client side; the repository
      does not even know about them.</para>
  </sect1>

  <sect1 id="goals.i18n">
    <title>I18N/Multilingual support</title>

    <para>Subversion is internationalized &ndash; commands, user messages, and
      errors can be customized to the appropriate human language at build-time
      (or run time, if that's not much harder).</para>

    <para>File names and contents may be multilingual; Subversion does not
      assume an ASCII-only universe.  For purposes of keyword expansion and
      line-end conversion, Subversion also understands the UTF-* encodings (but
      not necessarily all of them by the first release).</para>
  </sect1>

  <sect1 id="goals.branching-and-tagging">
    <title>Branching and tagging</title>
  
    <para>Subversion supports branching and tagging with one efficient
      operation: `clone'.  To clone a tree is to copy it, to create another
      tree exactly like it (except that the new tree knows its ancestry
      relationship to the old one).</para>

    <para>At the moment of creation, a clone requires only a small, constant
      amount of space in the repository &ndash; most of its storage is shared
      with the original tree.  If you never commit anything on the clone, then
      it's just like a CVS tag.  If you start committing on it, then it's a
      branch.  Voila!  This also implies CVS's "vendor branching" feature,
      since Subversion has real rename and directory support.</para>
  </sect1>

  <sect1 id="goals.misc">
    <title>Miscellaneous new behaviors</title>

    <sect2 id="goals.misc.logmsgs">
      <title>Log messages</title>

      <para>Subversion has a flexible log message policy (a small matter, but
        one dear to our hearts).</para>

      <para>Log messages should be a matter of project policy, not version
        control software policy.  If a user commits with no log message, then
        Subversion defaults to an empty message.  (CVS tries to require log
        messages, but fails: we've all seen empty log messages in CVS, where
        the user committed with deliberately empty quotes.  Let's stop the
        madness now.)</para>
    </sect2>

    <sect2 id="goals.misc.diffplugins">
      <title>Client side diff plug-ins</title>

      <para>Subversion supports client-side plug-in diff programs.</para>

      <para>There is no need for Subversion to have every possible diff
        mechanism built in.  It can invoke a user-specified client-side diff
        program on the two revisions of the file(s) locally.</para>

      <para>(Note:  This feature does not exist yet, but is planned for
        post-1.0.)</para>
    </sect2>

    <sect2 id="goals.misc.merging">
      <title>Better merging</title>

      <para>Subversion remembers what has already been merged in and what
        hasn't, thereby avoiding the problem, familiar to CVS users, of
        spurious conflicts on repeated merges.</para>

      <para>(Note:  This feature does not exist yet, but is planned for
        post-1.0.)</para>

      <para>For details, see <xref
          linkend="model.merging-and-ancestry"/>.</para>
    </sect2>

    <sect2 id="goals.conflicts">
      <title>Conflicts resolution</title>

      <para>For text files, Subversion resolves conflicts similarly to CVS, by
        folding repository changes into the working files with conflict
        markers.  But, for <emphasis>both</emphasis> text and binary files,
        Subversion also always puts the old and new pristine repository
        revisions into temporary files, and the pristine working copy revision
        in another temporary file.</para>

      <para>Thus, for any conflict, the user has four files readily at
        hand:</para>

      <orderedlist numeration="arabic">
        <listitem><para>the original working copy file with local
            mods</para></listitem>
        <listitem><para>the older repository file</para></listitem>
        <listitem><para>the newest repository file</para></listitem>
        <listitem><para>the merged file, with conflict
            markers</para></listitem>
      </orderedlist>

      <para>and in a binary file conflict, the user has all but the
        last.</para>

      <para>When the conflict has been resolved and the working copy is
        committed, Subversion automatically removes the temporary pristine
        files.</para>

      <para>A more general solution would allow plug-in merge resolution tools
        on the client side; but this is not scheduled for the first release).
        Note that users can use their own merge tools anyway, since all the
        original files are available.</para>
    </sect2>
  </sect1>
</chapter>
