<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sect1 SYSTEM "../../../dtd/dblite.dtd">
<sect1 id="tsvn-dug-branchtag">
  <title>Branching / Tagging</title>
  <indexterm>
    <primary>branch</primary>
  </indexterm>
  <indexterm>
    <primary>tag</primary>
  </indexterm>
  <indexterm>
    <primary>copy</primary>
  </indexterm>
  <indexterm>
    <primary>mark release</primary>
  </indexterm>
  <?dbhh topicname="HIDD_COPY"?>
  <para>
    One of the features of version control systems is the ability
    to isolate changes onto a separate line of development.
    This line is known as a <firstterm>branch</firstterm>.
    Branches are often used to try out new features without
    disturbing the main line of development with compiler
    errors and bugs. As soon as the new feature is stable enough
    then the development branch is <firstterm>merged</firstterm>
    back into the main branch (trunk).
  </para>
  <para>
    Another feature of version control systems is the ability
    to mark particular revisions (e.g. a release version),
    so you can at any time recreate a certain build or
    environment. This process is known as <firstterm>tagging</firstterm>.
  </para>
  <para>
    Subversion does not have special commands for branching
    or tagging, but uses so-called <quote>cheap copies</quote>
    instead. Cheap copies are similar to hard links in Unix, which means
    that instead of making a complete copy in the repository, an internal
    link is created, pointing to a specific tree/revision. As a result
    branches and tags are very quick to create, and take up almost
    no extra space in the repository.
  </para>
  <sect2 id="tsvn-dug-branch-1">
    <title>Creating a Branch or Tag</title>
    <para>
      If you have imported your project with the recommended
      directory structure, creating a branch or tag version is very simple:
      <figure id="tsvn-dug-branchtag-dia-1">
        <title>The Branch/Tag Dialog</title>
        <graphic fileref="../images/Copy.png"/>
      </figure>
      Select the folder in your working copy which you want to copy
      to a branch or tag, then select the command
      <menuchoice>
        <guimenu>TortoiseSVN</guimenu>
        <guimenuitem>Branch/Tag...</guimenuitem>
      </menuchoice>.
    </para>
    <para>
      The default destination URL for the new branch
      will be the source URL on which your working copy is based.
      You will need to edit that URL to the new path for your branch/tag.
      So instead of
      <screen>
https://svn.example.com/repos/ProjectName/trunk
      </screen>
      you might now use something like
      <screen>
https://svn.example.com/repos/ProjectName/tags/Release_1.10
      </screen>
      If you can't remember the naming convention you used last time,
      click the button on the right to open the repository browser
      so you can view the existing repository structure.
    </para>
    <important>
      <title>intermediate folders</title>
      <para>
        When you specify the target URL, all the folders
        up to the last one must already exist or you will
        get an error message. In the above example, the URL
        <literal>https://svn.example.com/repos/ProjectName/tags/</literal>
        must exist to create the <literal>Release_1.10</literal>
        tag.
      </para>
      <para>
        However if you want to create a branch/tag to an URL
        that has intermediate folders that don't exist yet
        you can check the option <option>Create intermediate folders</option>
        at the bottom of the dialog. If that option is activated,
        all intermediate folders are automatically created.
      </para>
      <para>
        Note that this option is disabled by default to avoid
        typos. For example, if you typed the target URL as
        <literal>https://svn.example.com/repos/ProjectName/Tags/Release_1.10</literal>
        instead of
        <literal>https://svn.example.com/repos/ProjectName/tags/Release_1.10</literal>,
        you would get an error with the option disabled, but
        with the option enabled a folder <literal>Tags</literal>
        would be automatically created, and you would end up with
        a folder <literal>Tags</literal> and a folder <literal>tags</literal>.
      </para>
    </important>
    <para>
      Now you have to select the source of the copy. Here you have
      three options:
      <variablelist>
        <varlistentry>
          <term>HEAD revision in the repository</term>
          <listitem>
            <para>
              The new branch is copied directly in the repository
              from the HEAD revision. No data needs to be transferred
              from your working copy, and the branch is created
              very quickly.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Specific revision in the repository</term>
          <listitem>
            <para>
              The new branch is copied directly in the repository
              but you can choose an older revision. This is useful
              if you forgot to make a tag when you released your
              project last week. If you can't remember the revision
              number, click the button on the right to show the
              revision log, and select the revision number from
              there. Again no data is transferred from your working
              copy, and the branch is created very quickly.
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Working copy</term>
          <listitem>
            <para>
              The new branch is an identical copy of your local
              working copy. If you have updated some files to an
              older revision in your WC, or if you have made local
              changes, that is exactly what goes into the copy.
              Naturally this sort of complex tag may involve
              transferring data from your WC back to the repository
              if it does not exist there already.
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
    </para>
    <para>
      If you want your working copy to be switched to the newly created
      branch automatically, use the
      <guilabel>Switch working copy to new branch/tag</guilabel> checkbox.
      But if you do that, first make sure that your working copy does not
      contain modifications. If it does, those changes will be merged into
      the branch WC when you switch.
    </para>
    <para>
      If your working copy has other projects included with
      <literal>svn:externals</literal> properties, those externals will
      be listed at the bottom of the branch/tag dialog. For each external,
      the target path and the source URL is shown.
    </para>
    <para>
      If you want to make sure that the new tag always is in a consistent
      state, check all the externals to have their revisions pinned.
      If you don't check the externals
      and those externals point to a HEAD revision which might change
      in the future, checking out the new tag will check out that HEAD
      revision of the external and your tag might not compile anymore.
      So it's always a good idea to set the externals to an explicit revision
      when creating a tag.
    </para>
    <para>
      The externals are automatically pinned to either the current HEAD revision
      or the working copy BASE revision, depending on the source of the branch/tag:
      <table id="tsvn-dug-branch-1-table">
        <title>Pinned Revision</title>
        <tgroup cols="2">
          <colspec colnum="1"/>
          <colspec colnum="2"/>
          <thead>
            <row>
              <entry>Copy Source</entry>
              <entry>Pinned Revision</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry>HEAD revision in the repository</entry>
              <entry>external's repos HEAD revision</entry>
            </row>
            <row>
              <entry>Specific revision in repository</entry>
              <entry>external's repos HEAD revision</entry>
            </row>
            <row>
              <entry>Working copy</entry>
              <entry>external's WC BASE revision</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
    </para>
    <important>
      <title>externals within externals</title>
      <para>
        If a project that is included as an external has itself included externals,
        then those will not be tagged! Only externals that are direct children can
        be tagged.
      </para>
    </important>
    <para>
      Press <guibutton>OK</guibutton> to commit the new copy to the
      repository. Don't forget to supply a log message. Note that the
      copy is created <emphasis>inside the repository</emphasis>.
    </para>
    <para>
      Note that unless you opted to switch your working copy to the newly
      created branch, creating a Branch or Tag does <emphasis>not</emphasis>
      affect your working copy. Even if you create the branch from your WC,
      those changes are committed to the new branch, not to the trunk, so your
      WC may still be marked as modified with respect to the trunk.
    </para>
  </sect2>
  <sect2 id="tsvn-dug-branch-2">
    <title>Other ways to create a branch or tag</title>
    <para>
      You can also create a branch or tag without having a working copy.
      To do that, open the repository browser. You can there drag folders
      to a new location. You have to hold down the <keycap>Ctrl</keycap>
      key while you drag to create a copy, otherwise the folder gets moved,
      not copied.
    </para>
    <para>
      You can also drag a folder with the right mouse button. Once you
      release the mouse button you can choose from the context menu whether
      you want the folder to be moved or copied. Of course to create a branch
      or tag you must copy the folder, not move it.
    </para>
    <para>
      Yet another way is from the log dialog. You can show the log dialog
      for e.g. trunk, select a revision (either the HEAD revision at the
      very top or an earlier revision), right click and choose
      <menuchoice>
        <guimenuitem>create branch/tag from revision...</guimenuitem>
      </menuchoice>.
    </para>
  </sect2>
  <sect2 id="tsvn-dug-switch-1">
    <title>To Checkout or to Switch...</title>
    <?dbhh topicname="HIDD_SWITCH"?>
    <indexterm>
      <primary>switch</primary>
    </indexterm>
    <para>
      ...that is (not really) the question. While a checkout downloads
      everything from the desired branch in the repository to your working
      directory,
      <menuchoice>
        <guimenu>TortoiseSVN</guimenu>
        <guimenuitem>Switch...</guimenuitem>
      </menuchoice>
      only transfers the changed data to your
      working copy. Good for the network load, good for your patience. :-)
    </para>
    <para>
      To be able to work with your freshly generated branch or tag you
      have several ways to handle it. You can:
      <itemizedlist>
        <listitem>
          <para>
            <menuchoice>
              <guimenu>TortoiseSVN</guimenu>
              <guimenuitem>Checkout</guimenuitem>
            </menuchoice>
            to make a fresh checkout in an empty folder.
            You can check out to any location on your
            local disk and you can create as many working copies
            from your repository as you like.
          </para>
        </listitem>
        <listitem>
          <para>
            Switch your current working copy to the
            newly created copy in the repository. Again select the
            top level folder of your project and use
            <menuchoice>
              <guimenu>TortoiseSVN</guimenu>
              <guimenuitem>Switch...</guimenuitem>
            </menuchoice>
            from the context menu.
          </para>
          <para>
            In the next dialog enter the URL of the branch you just created.
            Select the
            <guilabel>Head Revision</guilabel>
            radio button and click on
            <guibutton>OK</guibutton>.
            Your working copy is switched to the new branch/tag.
          </para>
          <para>
            Switch works just like Update in that it never discards your
            local changes. Any changes you have made to your working copy
            which have not yet been committed will be merged when you
            do the Switch. If you do not want this to happen then you
            must either commit the changes before switching, or revert
            your working copy to an already-committed revision (typically HEAD).
          </para>
        </listitem>
        <listitem>
          <para>
            If you want to work on trunk and branch, but don't want
            the expense of a fresh checkout, you can use Windows Explorer
            to make a copy of your trunk checkout in another folder, then
            <menuchoice>
              <guimenu>TortoiseSVN</guimenu>
              <guimenuitem>Switch...</guimenuitem>
            </menuchoice>
            that copy to your new branch.
          </para>
        </listitem>
      </itemizedlist>
      <figure id="tsvn-dug-switch-dia-1">
        <title>The Switch Dialog</title>
        <graphic fileref="../images/Switch.png"/>
      </figure>
    </para>
    <para>
      Although Subversion itself makes no distinction between tags
      and branches, the way they are typically used differs a bit.
      <itemizedlist>
        <listitem>
          <para>
            Tags are typically used to create a static snapshot of the
            project at a particular stage. As such they are not normally
            used for development - that's what branches are for, which
            is the reason we recommended the
            <filename>/trunk /branches /tags</filename>
            repository structure in the first place. Working on a tag
            revision is <emphasis>not a good idea</emphasis>, but
            because your local files are not write protected there is
            nothing to stop you doing this by mistake.
            However, if you try to commit to a path in the repository
            which contains <filename>/tags/</filename>, TortoiseSVN will
            warn you.
          </para>
        </listitem>
        <listitem>
          <para>
            It may be that you need to make further changes to a
            release which you have already tagged. The correct way
            to handle this is to create a new branch from the tag
            first and commit the branch. Do your Changes on this
            branch and then create a new tag from this new branch, e.g.
            <filename>Version_1.0.1</filename>.
          </para>
        </listitem>
        <listitem>
          <para>
            If you modify a working copy created from
            a branch and commit, then all changes go to the new
            branch and <emphasis>not</emphasis> the trunk.
            Only the modifications are stored.
            The rest remains a cheap copy.
          </para>
        </listitem>
      </itemizedlist>
    </para>
  </sect2>
</sect1>
