@need 3200

@node Elementary Branches -- Maintaining Private Changes
@chapter Elementary Branches -- Maintaining Private Changes

In this chapter, we'll begin to explore the concept of @geindex branching
@dfn{branching},
which you may be familiar with from other revision control systems.


If you are already familiar with the concept, you should be aware that
branching in @code{arch} almost certainly goes far beyond what you are
accustomed to.


Regardless of whether or not you are familiar with the concept, fear
not -- we'll be starting slow:

@need 3200

@section A Branching Scenario -- The Need for Private Changes

Let's suppose for the moment that the @code{hello-world} project is making
its sources available as a public, read-only mirror (see @ref{Shared and Public Archives}).


Early on, you (someone not involved in the @code{hello-world} project)
decides that you'll want to use their program, but that you'll need to
make some local changes.


As a sort of toy example, let's suppose that you've decided that in
your environment, saying @geindex hello world
@dfn{hello world} is unacceptable -- you really
require the more correctly punctuated @geindex hello, world
@dfn{hello, world}.


Now, here's the problem:  sure, you can download their sources and
make that change.  But meanwhile, the project is going to keep
working.  They're going to keep making changes.   So, you'll be faced
with a perpetual task of repeatedly downloading their latest sources
and copying your changes to their latest version.


@code{arch} can help automate that task, and this chapter explains how.




@need 3200

@section Making a Branch from a Remote Project in a Local Archive

@geindex tag



In the examples that follow, you'll be changing roles.  Instead of
"playing" Alice or Bob, the programmers on the @code{hello-world}
project, you'll be playing Candice: a third party.


Let's start by giving Candice her own archive to use, and making that
the default archive:

@example
@group

@end group
@group
        % larch make-archive lord@@emf.net--2003-candice \
                             ~/@{archives@}/2003-candice
@end group
@group

@end group
@group
        % larch my-default-archive lord@@emf.net--2003-candice
        default archive set (lord@@emf.net--2003-candice)
@end group
@group

@end group
@end example

(You can review what those commands do by reading @ref{Creating a New Archive}.)


Candice needs to create a @code{hello-world} project in her own archive.
She can use:

@example
@group

@end group
@group
        % larch make-category hello-world
        % larch make-branch hello-world--candice
        % larch make-version hello-world--candice--0.1
@end group
@group

@end group
@end example

She doesn't @emph{have} to use the same project name that Alice and Bob are
using and, in fact, in this case she chose a different branch name.
(To review those commands, see @ref{Starting a New Project}.)


When Alice and Bob created their archive, they used @code{import} to create
the first revision.  Since we're creating a @emph{branch}, we'll use a
different command.


For the sake of example, let's suppose Candice is going to start from
the @code{patch-1} revision of Alice and Bob's archive:

@example
@group

@end group
@group
    % larch tag \
        lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-1 \
        hello-world--candice--0.1
    [....]
@end group
@group

@end group
@end example

There are a few things worth noting about that command.


First, note that we used a @emph{@strong{fully qualified revision name}} to refer to
Alice and Bob's @code{patch-1} revision.  That's because that revision is
in some archive other than the current default archive.  (See
@strong{Working with Several Archives at Once} in @ref{Shared and Public Archives}.)


Next, note that we specified the @code{patch-1} revision explicitly.  If we
had left of the @code{--patch-1} suffix, then the @code{tag} command would
assume we meant the @emph{latest} revision in Alice and Bob's archive
(which happens to be @code{patch-3}).




@need 3200

@section What tag Just Did

After using @code{tag}, Candice now has a new revision in her archive:

@example
@group

@end group
@group
   % larch revisions --summary hello-world--candice--0.1
   base-0
       tag of lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-1
@end group
@group


@end group
@end example

She can retrieve that revision in the usual way:

@example
@group

@end group
@group
   % larch get hello-world--candice--0.1 hw-candice
   [...]
@end group
@group

@end group
@group
   % ls hw-candice
   hw.c         main.c          @{arch@}
@end group
@group

@end group
@end example

@strong{Nifty arch Feature:} If you've followed along closely, you should
have noticed that Candice created a branch in her archive from an arch
revision stored in another archive entirely.  In our examples, both of
these archives happen to be on the local file system but that isn't
necessary: Candice could have formed her branch even if she was
accessing Alice and Bob's archive over the network.


@strong{Usage Caution:}  Candice's job isn't quite done yet.   The next 
section explains another step she'll @emph{probably} want to take.




@need 3200

@section Caching a tag Revision

@geindex archive-cache-revision



Candice used @code{tag} to create a branch from Alice and Bob's archive.
When she uses @code{get} to check-out that revision, what happens?  Roughly
speaking, @code{arch} notices that the revision is a branch, then consults
Alice and Bob's archive to really get the source.


The question then arises: what if Alice and Bob's archive "goes
away"?  As things stand, if that happens, Candice will no longer be
able to @code{get} from her branch.


She can fix that though by caching in her archive all of the
information needed to build the revision:

@example
@group

@end group
@group
   % larch archive-cache-revision hello-world--candice--0.1--base-0
   [...]
@end group
@group

@end group
@end example

@noindent
and confirm that that worked with:

@example
@group

@end group
@group
   % larch archive-cached-revisions hello-world--candice--0.1
   hello-world--candice--0.1--base-0
@end group
@group

@end group
@end example

Thereafter, @code{arch} will no longer rely on Alice and Bob's archive to
retrieve Candice's @code{base-0} revision.




@need 3200

@section Exploring the New Branch

Earlier, Candice created her branch and used @code{get} to check it out.
Let's examine that tree:

@example
@group

@end group
@group
        % cd ~/wd/hw-candice
@end group
@group

@end group
@group
        % larch logs
        lord@@emf.net--2003-candice/hello-world--candice--0.1
        lord@@emf.net--2003-example/hello-world--mainline--0.1
@end group
@group

@end group
@end example

Note that Candice's tree has patch logs both for Alice and Bob's
version, and for her own branch:

@example
@group

@end group
@group
    % larch log-ls --summary \
            lord@@emf.net--2003-example/hello-world--mainline--0.1
    base-0
        initial import
    patch-1
        Fix bugs in the "hello world" string
@end group
@group


@end group
@group
    % larch log-ls hello-world--candice--0.1
    base-0
        tag of \
        lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-1
@end group
@group


@end group
@end example

There are not any later changes on Candice's branch:

@example
@group
        % larch whats-missing hello-world--candice--0.1
        [no output]
@end group
@group
@end group
@end example

@noindent
but recall that Alice and Bob are already up to @code{patch-3}:

@example
@group
        % larch whats-missing -A lord@@emf.net--2003-example \
                hello-world--mainline--0.1
        patch-2
        patch-3
@end group
@group
@end group
@end example



@need 3200

@section Making a Local Change

After the initial @code{tag}, Candice can commit changes to her branch in
the usual way.


Let's suppose that she has edited @code{hw.c} so that it now reads (in
part):

@example
@group

@end group
@group
        % cat hw.c
        [...]
        void
        hello_world (void)
        @{
          (void)printf ("hello, world\n");
        @}
        [...]
@end group
@group

@end group
@end example

@noindent
and that's she's prepared a log message:

@example
@group

@end group
@group
    % cat ++log.hello-world--candice--0.1--lord@@emf.net--2003-candice
    Summary: Punctuated the output correctly
    Keywords: 
@end group
@group


@end group
@group
    This program should say "hello, world" not "hello world".
@end group
@group

@end group
@end example

Now she can simply commit in the usual way, creating her own @code{patch-1}
revision:

@example
@group

@end group
@group
   % larch commit
   [....]
@end group
@group

@end group
@group
   % larch revisions --summary hello-world--candice--0.1
   base-0
       tag of \
       lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-1
   patch-1
       Punctuated the output correctly
@end group
@group

@end group
@end example



@need 3200

@section Updating from a Branched-from Version

@geindex merging

@geindex log-for-merge



Meanwhile, Alice and Bob have gone on to create their revisions
@code{patch-2} and @code{patch-3}.   How can Alice add those changes to her
branch?


Well, really, @code{arch} provides lots of techniques.  Using commands
we've already introduced, she could use either @code{update} or @code{replay}.
In this example, we'll demonstrate using @code{replay}.

@example
@group

@end group
@group
        % cd ~/wd/hw-candice
@end group
@group

@end group
@group
        % larch replay --in-place \
                -A lord@@emf.net--2003-example \
                . \
                hello-world--mainline--0.1
        [...]
@end group
@group

@end group
@end example

Note that we used a @code{-A} argument to say which archive we are
replaying changes from, and a version name to say which changes we
want.  In this case, @code{replay} applied the changesets for @code{patch-2} and
@code{patch-3} to Candice's tree.


This use of @code{replay} is a form of @geindex merging
@dfn{merging}:  Candice's local changes
have been merged with Alice and Bob's @code{mainline} changes.


@strong{Learning Note:}  If you're following along with the examples, you
should examine @code{hw.c} and notice that Candice's change to the @code{printf}
string and Alice's addition of a "copywrong" notice are both
included.


@strong{Learning Note:} You should also check out a second copy of Candice's
@code{patch-1} revision and experiment with doing the same merge using
@code{update} instead of @code{replay}.  You might have to look at @code{larch update
-help} to figure out exactly what options and arguments to provide.


Note also that, so far, we've only made these changes to Candice's
project tree -- they haven't been checked into Candice's archive.  To
actually record the merge in her archive, she'll have to make a log
message and commit in the usual way (see @ref{Checking-in Changes}).


There is, however, one more convenience to point out.  When Candice
writes her log message, she'll presumably want to note that the merge
took place and what it involves.  @code{arch} includes a command whose
output is ideal for inclusion in such a log message:

@example
@group

@end group
@group
  % cd ~/wd/hw-candice
@end group
@group

@end group
@group
  % larch log-for-merge
  Patches applied:
@end group
@group

@end group
@group
    * lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-3
       added copywrong statements
@end group
@group

@end group
@group
    * lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-2
       commented return from main
@end group
@group

@end group
@end example



@need 3200

@section How It Works -- tag and Elementary Branches

What did @code{tag} do?  Let's look at Candice's archive:

@example
@group

@end group
@group
        % cd ~/@{archives@}
        % cd 2003-candice
        % cd hello-world
        % cd hello-world--candice
        % cd hello-world--candice--0.1
@end group
@group

@end group
@group
        % ls
        +version-lock   =README         base-0          patch-1
        patch-2
@end group
@group

@end group
@end example

Of particular interest is the @code{base-0} revision -- the one created by
@code{tag}:

@example
@group

@end group
@group
        % cd base-0
@end group
@group

@end group
@group
        % ls
        CONTINUATION
        hello-world--candice--0.1--base-0.patches.tar.gz
        hello-world--candice--0.1--base-0.tar.gz
        log
@end group
@group

@end group
@group
        % cat CONTINUATION
        lord@@emf.net--2003-example/hello-world--mainline--0.1--patch-1
@end group
@group

@end group
@end example

The file @code{CONTINUATION} identifies this revision as a @code{tag} revision.
It's contents tell us what revision we branched from.


The changeset for this revision (@code{....patches.tar.gz}) was also
created by @code{tag}.  If you explore that changeset (recall @code{get-patch}
and @code{patch-report}) you'll see that all it does is add a log entry to
the tree's patch log.


The source file (@code{...base-0.tar.gz}) was created by
@code{archive-cache-revision}.   It contains a complete copy of Candice's
@code{base-0} revision.  Since that file is there, @code{get} is not obligated
to look at Alice and Bob's archive to construct this revision.







