The Hackerlab at `regexps.com`

## Patch Logs and Project Tree History

up: arch Meets hello-world next: Development Branches -- The star-merge Style of Cooperation prev: Elementary Branches -- Maintaining Private Changes

In the previous chapter, we began to learn about branching and merging. We saw how commands like `missing` , `update` , and `replay` can be used to keep track of and apply changes from multiple branches of a project.

In this chapter, we'll explain a bit about patch logs : the mechanism that is used to keep track of the history of a project tree, including that part of the history that is used for intelligent merging.

You should recall first encountering patch logs in earlier chapters (for example, when first initializing a project tree, in Starting a New Source Tree). In this chapter, patch logs are explained in greater depth.

### Project Trees Have Patch Logs

Recall that every initial import, tag revision, and changeset revision in an archive has an associated log message. That message consists of the headers and body that you supply to commands such as `import` and `commit` , plus additional headers that are automatically generated by `arch` .

When a project tree is first imported to an archive, the patch log entry for the new revision is added to the tree. When a `commit` takes place, as part of the process of committing, the log entry for the new revision is added to the tree. If you `get` a revision created by the `tag` command, you'll also find that it contains a patch log entry for the tag revision.

Patch log entries accumulate. Thus, for example, each commit adds a new log entry and all earlier log entries are preserved. Each tag revision includes not only the entry for the tag, but all log entries inherited from the revision being tagged.

Returning to our earlier examples, let's take a look at Alice and Bob's `patch-2` revision:

            % cd ~/wd

            [... remove directories from earlier examples ...]

            % tla get -A lord@emf.net--2003-example \
                        hello-world--mainline--0.1--patch-2 \
                        hw-AnB-2

            [...]

            % cd ~/hw-AnB-2

First, we note that patch logs are sorted by `arch` version names. This tree has logs from only one version:

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

Within that version, it has logs for the initial import, and two changesets:

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

Examining one of those log entries in particular:

            % tla cat-log -A lord@emf.net--2003-example \
                            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--mainline--0.1/[...]/patch-log/patch-2
            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.

we can see, for example, that the `patch-2` changeset modified the file `main.c` and added a new file, the log entry itself (whose name is abbreviated in the output displayed above).

Other examples worth considering come from Candice's tree. Recall that she used `tag` to fork from Alice and Bob's tree at their `patch-1` revision. Therefore we see:

            % cd ~/wd

            % tla get -A candice@candice.net--2003-candice \
                        hello-world--candice--0.1--patch-2 \
                        hw-C-0

            [...]

            % cd ~/hw-C-0

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

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

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

### How It Works -- missing

In earlier chapters, you learned how the command `missing` can tell you about changes commited to archives, but not yet present in a given project tree (see Studying Why Alice Can Not commit and Exploring the New Branch).

It should now be easy to understand how those commands work. `arch` can find the list of all revisions in a given version using the `revisions` command:

            % tla revisions -A lord@emf.net--2003-example \
                              hello-world--mainline--0.1
            base-0
            patch-1
            patch-2
            patch-3

Those are the logs in the archive. `arch` can find out the list of revisions for which a project tree has log entries with `logs` :

            % tla logs -A lord@emf.net--2003-example \
                           hello-world--mainline--0.1
            base-0
            patch-1
            patch-2

The difference between those two lists is the output of `missing` :

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

### The Concept of Change History and Tree Ancestry

Patch logs give important insight into the history of a tree. There are two views worth mentioning: the change history view, and the tree ancestry view.

#### Change History

When a tree has a log for a given `commit` changeset, that means that the changes from that `commit` have been applied to the tree: the `commit` changeset is part of the "change history" of the tree. If the changeset were a bug fix, for example, then this is a likely indication that the bug fix is present in the tree.

Note: The mere fact that a given changeset is part of the change history of a tree isn't absolute proof that the changes made by that changeset are present in the tree. For example, those changes might have been "undone" by a later change. Nevertheless, the change history of a tree is a useful tool for exploring and understanding its state.

### Tree Ancestry

Informally, we say that an archived revision is a tree ancestor of a given project tree if it has patch log entries for all of the revisions in the version of that archived revision up to to the archived revision itself.

Thus, for example, Candice's tag revision has Alice and Bob's `patch-1` revision as an ancestor because it has logs for Alice and Bob's revisions:

            base-0
            patch-1

And Candices's `patch-2` revision, which merges in changes from Alice and Bob's `patch-2` and `patch-3` , has both of those additional revisions as ancestors (see Updating from a Branched-from Version).

### Automated ChangeLogs

The command `tla changelog` generates a GNU-style `ChangeLog` file from a patch log:

      % cd ~/wd

      % tla get -A candice@candice.net--2003-candice \
                  hello-world--candice--0.1 \
                  hw-C-latest
      [....]

      % cd ~/wd/hw-C-latest

      % tla changelog
      # do not edit -- automatically generated by arch changelog
      # arch-tag: automatic-ChangeLog-- [...]
      #

      2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       patch-2

          Summary:
            merge from mainline sources
          Revision:
            hello-world--candice--0.1--patch-2

          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

          new files:
           {arch}/ [...] /hello-world--mainline--0.1 [...] /patch-2
           {arch}/ [...] /hello-world--mainline--0.1 [...] /patch-3

          modified files:
           hw.c main.c

          new patches:
           lord@emf.net--2003-example/hello-world--mainline--0.1--patch-2
           lord@emf.net--2003-example/hello-world--mainline--0.1--patch-3

      2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       patch-1

          Summary:
            Punctuated the output correctly
          Revision:
            hello-world--candice--0.1--patch-1

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

          modified files:
           hw.c

      2003-01-30 GMT  Tom (testing) Lord <lord@emf.net>       base-0

          Summary:
            tag of lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1
          Revision:
            hello-world--candice--0.1--base-0

          (automatically generated log message)

          new patches:
           lord@emf.net--2003-example/hello-world--mainline--0.1--base-0
           lord@emf.net--2003-example/hello-world--mainline--0.1--patch-1

Note that the generated `ChangeLog` includes a `tagline` . If you save the output of the `changelog` command in a project tree, either using tagline ids or giving it an explicit id that matches the `tagline` s id, the commands such as `commit` will automatically keep the `ChangeLog` up to date.

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