Key Distinction: A branch is a named, intentional fork.
Unnamed forks may be intentional, but most of the time, they're accidental and left unnamed. Fossil offers two primary ways to create named, intentional forks, a.k.a. branches. First:$ fossil commit --branch my-new-branch-nameThis is the method we recommend for most cases: it creates a branch as part of a check-in using the version in the current checkout directory as its basis. (This is normally the tip of the current branch, though it doesn't have to be. You can create a branch from an ancestor check-in on a branch as well.) After making this branch-creating check-in, your local working directory is switched to that branch, so that further check-ins occur on that branch as well, as children of the tip check-in on that branch. The second, more complicated option is:
$ fossil branch new my-new-branch-name trunk $ fossil update my-new-branch-name $ fossil commitNot only is this three commands instead of one, the first of which is longer than the entire simpler command above, you must give the second command before creating any check-ins, because until you do, your local working directory remains on the same branch it was on at the time you issued the command, so that the commit would otherwise put the new material on the original branch instead of the new one. In addition to those problems, the second method is a violation of the [https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it|YAGNI Principle]. We recommend that you wait until you actually need the branch before you create it using the first command above. The "trunk" is just another named branch in Fossil. It is simply the default branch name for the first check-in and every check-in made as one of its direct descendants. It is special only in that it is Fossil's default when it has no better idea of which branch you mean.
By Fossil itself when two users check in children to the same
leaf of a branch, as in Figure 2.
If the fork occurs because
autosync is disabled on one or both of the repositories or because
the user doing the check-in has no network connection at the moment
of the commit, Fossil has no way of knowing that it is creating a
fork until the two repositories are later synchronized.
By Fossil when the cloning hierarchy is more
than 2 levels deep.
[./sync.wiki|Fossil's synchronization protocol] is a two-party
negotiation; syncs don't automatically propagate up the clone tree
beyond that. Because of that, if you have a master repository and
Alice clones it, then Bobby clones from Alice's repository, a
check-in by Bobby that autosyncs with Alice's repo will not
also autosync with the master repo. The master doesn't get a copy of
Bobby's check-in until Alice separately syncs with the master.
If Carol cloned from the master repo and checks something in that
creates a fork relative to Bobby's check-in, the master repo won't
know about that fork until Alice syncs her repo with the master.
Even then, realize that Carol still won't know about the fork until
she subsequently syncs with the master repo.
One way to deal with this is to just accept it as a fact of using a
[https://en.wikipedia.org/wiki/Distributed_version_control|Distributed
Version Control System] like Fossil.
Another option, which we recommend you consider carefully, is to
make it a local policy that check-ins be made only directly against the master
repo or one of its immediate child clones so that the autosync
algorithm can do its job most effectively. Any clones deeper than
that should be treated as read-only and thus get a copy of the new
state of the world only once these central repos have negotiated
that new state. This policy avoids a class of inadvertent fork you
might not need to tolerate. Since [#bad-fork|forks on long-lived
shared working branches can end up dividing a team's development
effort], a team may easily justify this restriction on distributed
cloning.
You've automated Fossil, so you use
fossil commit --allow-fork commands to prevent Fossil from
refusing the check-in simply because it would create a fork.
If you are writing such a tool — e.g. a shell script to make
multiple manipulations on a Fossil repo — it's better to make it
smart enough to detect this condition and cope with it, such as
by making a call to [/help/update | fossil update]
and checking for a merge conflict. That said, if the alternative is
losing information, you may feel justified in creating forks that an
interactive user must later manually clean up with fossil merge
commands.
$ fossil mergeNormally you need to pass arguments to fossil merge to tell it what you want to merge into the current basis view of the repository, but without arguments, the command seeks out and fixes forks.
The working check-out directory she's using at the moment was on a different branch at the time Alan made check-in 3, so Fossil sees that as the tip at the time she switches her working directory to that branch with a fossil update $BRANCH command. (There is an implicit autosync in that command, if the option was enabled at the time of the update.)
The same thing, only in a fresh checkout directory with a [/help/open | fossil open $REPO $BRANCH] command.
Alan makes his check-in 3 while Betty has check-in 1 or 2 as the tip in her local clone, but because she's working with an autosync'd connection to the same upstream repository as Alan, on attempting what will become check-in 4, she gets the "would fork" message from fossil commit, so she dutifully updates her clone and tries again, moving her work to be a child of the new tip, check-in 3. (If she doesn't update, she creates a second fork, which simply complicates matters beyond what we need here for our illustration.)
A branch is a set of check-ins with the same value for their "branch" property.
A leaf is a check-in with no children in the same branch.
A closed leaf is any leaf with the closed tag. These leaves are intended to never be extended with descendants and hence are omitted from lists of leaves in the command-line and web interface.
A open leaf is a leaf that is not closed.
A fork is when a check-in has two or more direct (non-merge) children in the same branch.
A branch point occurs when a check-in has two or more direct (non-merge) children in different branches. A branch point is similar to a fork, except that the children are in different branches.