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.
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. In this example, we will see how to use a single, central archive shared among several developers.
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.
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 [...]
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.
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 in Importing the First Revision).
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.
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).
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).