Next: , Previous: Shared and Public Archives, Up: Collaborating With Other People


5.4 Elementary Branches – Maintaining Private Changes

In this chapter, we'll begin to explore the concept of 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 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:

5.4.1 A Branching Scenario – The Need for Private Changes

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

Early on, you (someone not involved in the 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 hello world is unacceptable – you really require the more correctly punctuated 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.

arch can help automate that task, and this chapter explains how.

5.4.2 Making a Branch from a Remote Project in a Local Archive

In the examples that follow, you'll be changing roles. Instead of "playing" Alice or Bob, the programmers on the 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:

             % tla make-archive candice@candice.net--2003-candice \
                                  ~/archives/2003-candice

             % tla my-default-archive candice@candice.net--2003-candice
             default archive set (candice@candice.net--2003-candice)

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

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

             % tla archive-setup  hello-world--candice--0.1

She doesn't 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 Starting a New Project.)

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

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

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

There are a few things worth noting about that command.

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

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

5.4.3 What tag Just Did

After using tag, Candice now has a new revision in her archive:

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

She can retrieve that revision in the usual way:

        % tla get hello-world--candice--0.1 hw-candice
        [...]

        % ls hw-candice
        hw.c         main.c          {arch}

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.

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

5.4.4 Caching a tag Revision

Candice used tag to create a branch from Alice and Bob's archive. When she uses get to check-out that revision, what happens? Roughly speaking, 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 get from her branch.

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

        % tla cacherev hello-world--candice--0.1--base-0
        [...]

and confirm that that worked with:

        % tla cachedrevs hello-world--candice--0.1
        hello-world--candice--0.1--base-0

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

5.4.5 Exploring the New Branch

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

             % cd ~/wd/hw-candice

             % tla log-versions
             candice@candice.net--2003-candice/hello-world--candice--0.1
             lord@emf.net--2003-example/hello-world--mainline--0.1

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

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

         % tla logs --summary hello-world--candice--0.1
         base-0
             tag of \
             lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

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

             % tla missing hello-world--candice--0.1
             [no output]

but recall that Alice and Bob are already up to patch-3:

             % tla missing -A lord@emf.net--2003-example \
                     hello-world--mainline--0.1
             patch-2
             patch-3

5.4.6 Making a Local Change

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

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

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

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

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

         This program should say "hello, world" not "hello world".

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

        % tla commit
        [....]

        % tla 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

5.4.7 Updating from a Branched-from Version

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

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

             % cd ~/wd/hw-candice

             % tla replay -A lord@emf.net--2003-example \
                     hello-world--mainline--0.1
             [...]

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

This use of replay is a form of merging: Candice's local changes have been merged with Alice and Bob's mainline changes.

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

Learning Note: You should also check out a second copy of Candice's patch-1 revision and experiment with doing the same merge using update instead of replay. You might have to look at tla 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 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. arch includes a command whose output is ideal for inclusion in such a log message:

       % cd ~/wd/hw-candice

       % tla log-for-merge
       Patches applied:

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

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

5.4.8 How It Works – tag and Elementary Branches

What did tag do? Let's look at Candice's archive:

             % cd ~/archives
             % cd 2003-candice
             % cd hello-world
             % cd hello-world--candice
             % cd hello-world--candice--0.1

             % ls
             +version-lock   base-0          patch-1
             patch-2

Of particular interest is the base-0 revision – the one created by tag:

             % cd base-0

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

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

The file CONTINUATION identifies this revision as a tag revision. Its contents tell us what revision we branched from.

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

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