The Hackerlab at regexps.com

The update/commit Style of Cooperation

up: arch Meets hello-world
next: Introducing Changesets
prev: Shared and Public Archives

In earlier chapters, you learned how to add a project to an archive, store the initial sources, store changes made to those sources, and retrieve revisions from the archive.

In the previous chapter, you learned how to make an archive network accessible.

This chapter will begin to explore how multiple programmers can share an archive, with each of them making changes to a particular project.

You should take note at the outset that there are really many subtle variations on how programmers can share archives and otherwise cooperate on a given project. We're starting here with one of the very simplest techniques.

Alice and Bob Hack main

Let's suppose that Alice and Bob are both working on the hello-world project and that they are sharing a single archive. In the examples that follow, we'll play both roles.

For starters, each programmer will need their own project tree:

        % cd ~/wd

        % [ ... remove any directories left from earlier examples ...]


        % tla get hello-world--mainline--0.1  hello-world-Alice
        [....]

        % tla get hello-world--mainline--0.1  hello-world-Bob
        [....]

Alice's task is to add some legal notices to each file. When she's done (but has not yet used commit to write her changes to the archive), the files look this way:

        % cd ~/wd/hello-world-Alice

        % head -3 main.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed.*/

        extern void hello_world (void);

        % head hw.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed. */

        #include <stdio.h>

Bob, meanwhile, has added a much-needed comment to main :

        % cd ~/wd/hello-world-Bob

        % cat main.c
        extern void hello_world (void);

        int
        main (int argc, char * argv[])
        {
          hello_world ();

          /* Exit with status 0
           */
          return 0;
        }


Note that the two programmers now have modified versions of hello-world , but neither programmer has the other's changes.

Bob commits First

Let's suppose that Bob is the first to try to commit his changes. Just to review, there are two steps.

First, Bob prepares a log message:

   % cd ~/wd/hello-world-Bob

   % tla make-log
   ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

   [Bob edits the log message.]

   % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example
   Summary: commented return from main
   Keywords: 

   Added a comment explaining how the return from `main'
   relates to the exit status of the program.


Then he calls commit :

   % tla commit
   [...]

Alice Can Not commit Yet

Now it's Alice's turn:

   % cd ~/wd/hello-world-Alice

   % tla make-log
   ++log.hello-world--mainline--0.1--lord@emf.net--2003-example

   [Alice edits the log message.]

   % cat ++log.hello-world--mainline--0.1--lord@emf.net--2003-example
   Summary: added copywrong statements
   Keywords: 

   Added copywrong statements to the source files so 
   that nobody can steal HowdyCorp's code.


And then tries to commit:

   % tla commit
   commit: tree is not up-to-date (missing latest revision is lord@emf.net--2003b--2003-example/hello-world--mainline--0.1--patch-2)

The problem here is that Bob's changes have already been stored in the archive, but Alice's tree doesn't reflect those changes.

Studying Why Alice Can Not commit

The commit command told Alice that her tree is "out of date". That means that changes have been committed to the archive that her tree doesn't have yet.

She can examine the situation in a little more depth by asking what her tree is missing:

        % tla missing
        patch-2

or for more detail:

        % tla missing --summary
        patch-2
            commented return from main

which you should recognize as the Summary: line from Bob's log message.

She can get even more detail with the (previously introduced) revisions command (see Storing the First Revision in the Archive).

She can view Bob's entire log message:

    % tla cat-archive-log hello-world--mainline--0.1--patch-2
    Revision: hello-world--mainline--0.1--patch-2
    Archive: lord@emf.net--2003-example
    Creator: Tom (testing) Lord <lord@emf.net>
    Date: Wed Jan 29 12:46:50 PST 2003
    Standard-date: 2003-01-29 20:46:50 GMT
    Summary: commented return from main
    Keywords: 
    New-files: {arch}/hello-world/[....]
    Modified-files: main.c
    New-patches: \
      lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2

    Added a comment explaining how the return from `main'
    relates to the exit status of the program.


By looking at the headers of that message, Alice can figure out, for example, that Bob modified the file main.c .

In later chapters, we'll explore more commands that Alice can use to study the changes that Bob made, but for now, let's turn to how Alice can add those changes to her tree.

The update Command

Alice needs to combine her changes with Bob's before she can commit her changes. One easy way to do that is the update command:

        % cd ~/wd

        % tla update --in-place hello-world-Alice
        [....]


Now she will find Bob's changes added to her tree:

        % cd hello-world-Alice

        % cat main.c
        /* Copywrong 1998 howdycorp inc.  All rights reversed. */

        extern void hello_world (void);

        int
        main (int argc, char * argv[])
        {
          hello_world ();

          /* Exit with status 0
           */
          return 0;
        }

        /* arch-tag: main module of the hello-world project
         */

Since no further changes are missing:

        % tla missing
        [no output]

commit is happy to proceed:

        % tla commit
        [....]

Learning Note: If you're following along with the examples, you should still have a tree in hello-world-Bob that has Bob's changes, but not Alice's. Try various commands for that directory to explore (missing , update , changes and so forth).

How it Works -- The update Command

A full explanation of how update works is a little beyond the scope of this chapter. You'll be able understand update in detail after a few of the later chapters (on changesets and patch logs).

For now, if you are familiar with diff and patch , you can think of it this way:

When update is run in Alice's tree, it notices that the archive is up to a patch-2 revision, but that her tree was checked out as a get of the patch-1 revision. update works in three steps:

First, it uses a command called mkpatch (which is kind of a fancier variation on diff ) to compute a changeset (a fancy patch set) that describes the changes Alice made to her tree.

Second, it checks out a copy of the patch-2 revision and replaces Alice's tree with that revision.

Third, update uses dopatch (a fancier patch ) to apply the changeset from the first step to the new tree.

You may be wondering how patch conflicts are handled. The examples above were carefully crafted to avoid any conflicts. Don't worry -- we'll get to that topic soon enough (see Inexact Patching -- How Conflicts are Handled).

arch Meets hello-world: A Tutorial Introduction to The arch Revision Control System
The Hackerlab at regexps.com