Overview
SHA1 Hash: | 2e275c14202446fca2bb8a48a8d15ed82d9bbc33 |
---|---|
Date: | 2009-01-23 21:24:00 |
User: | drh |
Comment: | First draft of the "branching" document. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Added art/branching.odp version [2b21dbbc28]
cannot compute difference between binary files
Added www/branch01.gif version [a288153196]
cannot compute difference between binary files
Added www/branch02.gif version [55c3567748]
cannot compute difference between binary files
Added www/branch03.gif version [3840bdbb5e]
cannot compute difference between binary files
Added www/branch04.gif version [908b4fc168]
cannot compute difference between binary files
Added www/branch05.gif version [4808cbf6e0]
cannot compute difference between binary files
Added www/branching.wiki version [55dd24e8cf]
@@ -1,1 +1,259 @@ +<h1 align="center"> +Branching, Forking, Merging, and Tagging +</h1> + +In a simple and perfect world, the development of a project would proceed +linearly, as shown in figure 1. + +<center><table border=1 cellpadding=10 hspace=10 vspace=10> +<tr><td align="center"> +<img src="branch01.gif"><br> +Figure 1 +</td></tr></table></center> + +Each circle represents a check-in. For the sake of clarity, the check-ins +are given small consecutive numbers. In a real system, of course, the +check-in numbers would be 40-character SHA1 hashes since it is not possible +to allocate collision-free sequential numbers is a distributed system. +But sequential numbers are easier to read, so we will substitute them for +the 40-character SHA1 hashes in this document. + +The arrows in figure 1 show evolution of the project. The initial +check-in is 1. Check-in 2 is derived from 1. In other words, check-in 2 +was created by making edits to check-in 1 and then committing those edits. +We say that 2 is a <i>child</i> of 1 +and that 1 is a <i>parent</i> of 2. +Check-in 3 is derived from check-in 2, making +3 a child of 2. We say that 3 is a <i>descendant</i> of both 1 and 2 and that 1 +and 2 are both <i>ancestors</i> of 3. + +We call the graph of check-ins a <i>tree</i>. Check-in 1 is the <i>root</i> +since it has no ancestors. Check-in 4 is a <i>leaf</i> of the tree since +it has no descendants. + +Alas, reality often interferes with the simple linear development of a +project. Suppose two programmers make independent modifications to check-in 2. +After both changes are checked in, we have a check-in graph that looks +like figure 2: + +<center><table border=1 cellpadding=10 hspace=10 vspace=10> +<tr><td align="center"> +<img src="branch02.gif"><br> +Figure 2 +</td></tr></table></center> + +The graph in figure 2 has two leaves: check-ins 3 and 4. Check-in 2 has +two children, check-ins 3 and 4. We call this stituation a <i>fork</i>. + +Fossil tries to prevent forks. Suppose the two programmers who were +editing check-in 2 are named Alice and Bob. Suppose Alice finished her +edits first and did a commit, resulting in check-in 3. Later, when Bob +tried to commit his changes, fossil would try to verify that check-in 2 +was still a leaf. Fossil would see that check-in 3 had occurred and would +abort Bob's commit attempt with a message "would fork". This allows Bob +to do a "fossil update" which would pull in Alices changes and merge them +together with his own changes. After merging, Bob could then commit +check-in 4 as a child of check-in 3 and the result would be a linear graph +as shown in figure 1. This is how CVS works. This is also how fossil +works in "autosync" mode. + +But it might be that Bob is off-network when he does his commit, so he +has no way of knowing that Alice has already committed her changes. +Or, it could be that Bob has turned of "autosync" mode in SQLite. Or, +maybe Bob just doesn't want to merge in Alices changes before he has +saved his own, so he forces the commit to occur using the "--force" option +to the fossil <b>commit</b> command. For whatever reason, two commits against +check-in 2 have occurred and now the tree has two leaves. + +So which version of the project is the "latest" in the sense of having +the most features and the most bug fixes? When there is more than +one leaf in the graph, you don't really know. So we like to have +graphs with a single leaf. + +To resolve this situation, Alice can use the fossil <b>merge</b> command +to me merge in Bob's changes in here local copy of check-in 3. Then she +can commit the results as check-in 5. This results in a tree as shown +in figure 3. + +<center><table border=1 cellpadding=10 hspace=10 vspace=10> +<tr><td align="center"> +<img src="branch03.gif"><br> +Figure 3 +</td></tr></table></center> + +Check-in 5 is a direct child of check-in 3 because it was created by editing +check-in 3. But check-in 5 also inherits the changes from check-in 4 by +virtual of the merge. So we say that check-in 5 is a <i>merge child</i> +of check-in 4 and that it is a <i>direct child</i> of check-in 3. +The graph is now back to a single leaf (check-in 5). + +We have already seen that if fossil is in autosync mode then Bob would +have been warned about the potential fork the first time he tried to +commit check-in 4. If Bob had updated his local check-out to merge in +Alice's check-in 3 changes, then committed, then the fork would have +never occurred. The resulting graph would have been linear, as shown +in figure 1. Really the graph of figure 1 is a subset of figure 3. +Hold your hand over the check-in 4 circle of figure 3 and then figure +3 looks exactly like figure 1 (except that the leaf has a different check-in +number, but that is just a notational difference - the two check-ins have +exactly the same content). In other words, figure 3 is really a superset +of figure 1. The check-in 4 of figure 3 captures addition state which +is omitted from figure 1. In check-in 4 of figure 3 is a copy +of Bob's local checkout before he merged in Alices changes. That snapshot +of Bob's changes independent of Alice's changes is omitted from figure 1. +Some people say that the approach taken in figure 3 is better because it +preserves this extra intermediate state. Others say that the approach +taken in figure 1 is better because it is much easier to visualize a +linear line of development and because the the merging happens automatically +instead of as a separate manual step. We will not take sides in this +debate. We will simply point out that fossil enables you to do it either way. + +<h2>Forking Versus Branching</h2> + +Forking and having more than one leaf in the check-in tree is usually +considered undesirable, and so forks are usually quickly resolved as +shown in figure 3 above. +But sometimes, one does want to have multiple leaves. For example, a project +might have one leaf that is the latest version of the project under +development and another leaf that is the latest version that has been +tested. +When multiple leaves are desirable, we call the phenomenon <i>branching</i> +instead of <i>forking</i>. +Figure 4 shows an example of a project where there are two branches, one +for development work and another for testing. + +<center><table border=1 cellpadding=10 hspace=10 vspace=10> +<tr><td align="center"> +<img src="branch04.gif"><br> +Figure 4 +</td></tr></table></center> + +The hypothetical scenario of figure 4 is this: The project starts and +progresses to a point where (at check-in 2) +it is ready to enter testing for its first release. +In a real project, of course, there might be hundreds or thousands of +check-ins before a project reaches this point, but for simplicity of +presentation we will say that the project is ready after check-in 2. +The project then splits into two branches that are used by separate +teams. The testing team, using the blue branch, finds and fixes a few +bugs. This is shown by check-ins 6 and 9. Meanwhile the development +team, working on the red branch, is busy adding features for the second +release. Of course, the development team would like to take advantage of +the bug fixes implemented by the testing team. So periodically, the +changes in the test branch are merged into the dev branch. This is +shown by the dashed merge arrows between check-ins 6 and 7 and between +check-ins 9 and 10. + +In both figures 2 and 4, check-in 2 has two children. In figure 2, +we called this a "fork". In diagram 4, we call it a "branch". What is +the difference? As far as the internal fossil data structure are +concerned, there is no difference. The distinction is in the intent. +In figure 2, the fact that check-in 2 has multiple children is an +accident that stems from concurrent development. In figure 4, giving +check-in 2 multiple children is a deliberate act. So, to a good +approximating, we define forking to be by accident and branching to +be by intent. Apart from that, they are the same. + +<h2>Tags And Properties</h2> + +Tags and properties are used in fossil to help express the intent, and +thus to distinguish between forks and branches. Figure 5 shows the +same scenario as figure 4 but with tags and properties added: + +<center><table border=1 cellpadding=10 hspace=10 vspace=10> +<tr><td align="center"> +<img src="branch05.gif"><br> +Figure 5 +</td></tr></table></center> + +A <i>tag</i> is a name that is attached to a check-in. A +<i>property</i> is a name/value pair. Internally, fossil implements +tags as properties with a NULL value. So, tags and properties really +are much the same thing, and henceforth we will use the word "tag" +to mean either a tag or a property. + +A tag can be either a one-time tag or an propagating tag or a cancellation. +A one-time tag only applies to the check-in to which it is attached. An +propagating tag applies to the check-in to which it is attached and also +to all direct descendants of that check-in. A <i>direct descendant</i> +is a descendant through direct children. Tags propagation does not +cross merges. Tag propagation also stops as soon +as it encounters another check-in with the same tag. A cancellation tag +is attached to a single check-in in order to either override a one-time +tag that was placed on that same check-in, or to block tag propagation. + +Every repository is created with a single empty check-in that has two +propagating tags. In figure 5, that initial empty check-in is check-in 1. +The <b>branch</b> tag tells (by its value) +what branch the check-in is a member of. +The default branch is called "trunk". All tags that begin with "<b>sym-</b>" +are symbolic name tags. When a symbolic name tag is attached to a +check-in, that allows you to refer to that check-in by its symbolic +name rather than by its 40-character SHA1 hash name. When a symbolic name +tag propagates (as does the <b>sym-trunk</b> tag) then referring to that +name is the same as referring to the most recent check-in with that name. +Thus the two tags on check-in once cause all decendents to be in the +"trunk" branch and to have the symbolic name "trunk". + +Check-in 4 has a <b>branch</b> tag which changes the name of the branch +to "test". The branch tag on check-in 4 propagates to check-ins 6 and 9. +But because tag propagation does not follow merge links, the <b>branch=test</b> +tag does not propagate to check-ins 7, 8, or 9. Note also that the +<b>branch</b> tag on check-in 4 blocks the propagation of <b>branch=trunk</b> +so that it cannot reach check-ins 6 or 9. This causes check-ins 4, 6, and +9 to be in the "test" branch and all others to be in the "trunk" branch. + +Check-in 4 also has a <b>sym-test</b> tag, which gives the symbolic name +"test" to check-ins 4, 6, and 9. Because tags do not propagate across +merges, check-ins 7, 8, and 9 do not inherit the <b>sym-test</b> tag and +are hence not known by the name "test". +To prevent the <b>sym-trunk</b> tag from propagating from check-in 1 +into check-ins 4, 6, and 9, there is a cancellation tag for +<b>sym-trunk</b> on check-in 4. The net effect of all of this is that +check-ins on the trunk go by the symbolic name of "trunk" and check-ins +that are on the test branch go by the symbolic name "test". + +The <b>bgcolor=blue</b> tag on check-in 4 causes the background color +of timelines to be blue for check-in 4 and its descendants. + +Figure 5 also shows two one-time tags on check-in 9. (The diagram does +not make a graphical distinction between one-time and propagating tags.) +The <b>sym-release-1.0</b> tag means that check-in 9 can be referred to +using the more meaningful name "release-1.0". The <b>closed</b> tag means +that check-in 9 is a "closed leaf". A closed leaf is a leaf that intended +to never have any childred. + +<h2>Review Of Terminology</h2> + +Here is a list of definitions of key terms: + + +<blockquote><dl> +<dt><b>Branch</b></dt> +<dd><p>A branch is a set of check-ins that have the same value for their +<dt><b>Leaf</b></dt> +<dd><p>A leaf is a check-in that has no children in the same branch.</p></dd> +<dt><b>Closed Leaf</b></dt> +<dd><p>A closed leaf is leaf that has the <b>closed</b> tag. Such leaves +are intented to never be extended with descendents and hence are omitted +from lists of leaves in the command-line and web interface.</p></dd> +<dt><b>Open Leaf</b></dt> +<dd><p>A open leaf is a leaf that is not closed.</p></dd> +<dt><b>Fork</b></dt> +<dd><p>A fork occurs when a check-in has two or more direct (non-merge) +children in the same branch.</p></dd> +<dt><b>Branch Point</b></dt> +<dd><p>A branch point occurs when a check-in has two or more direct (non-merge) +children in the different branches. A branch point is similar to a fork, +except that the children are in different branches.</p></dd> +</dl></blockquote> + +Check-in 4 of figure 3 is not a leaf because it has a child (check-in 5) +in the same branch. Check-in 9 of figure 5 also has a child (check-in 10) +but that child is in a different branch, so check-in 9 is a leaf. Because +of the <b>closed</b> tag check-in 9, it is a closed leaf. +Check-in 2 of figure 3 is considered a "fork" +because it has two children in the same branch. Check-in 2 of figure 5 +also has two children, but each child is in a different branch, hence in +figure 5, check-in 2 is considered a "branch point".
Modified www/concepts.wiki from [414be747ce] to [e17c6aa709].
@@ -212,13 +212,13 @@ <img src="concept2.gif" align="right" hspace="10"> <p>Fossil has two modes of operation: "autosync" and "non-autosync". Autosync mode works something like CVS or SVN in that it automatically keeps your work in sync with the central server. Non-autosync is -more like GIT, or Bitkeeper in that your local repository develops +more like GIT or Bitkeeper in that your local repository develops independently of your coworkers and you share your changes manually. -The interesting thing about fossil is that it supports both autosync +An interesting feature of fossil is that it supports both autosync and non-autosync work flows.</p> <p>The default setting for fossil is to be in autosync mode. You can change the autosync setting or check the current autosync setting using commands like:</p> @@ -382,10 +382,16 @@ <p>A stand-alone server is a great way to set of transient connections between coworkers for doing quick pushes or pulls. But you can also set up a permanent stand-alone server if you prefer. Just make arrangements for fossil to be launched with appropriate arguments after every reboot.</p> + +<p>If you just want a server to browse the built-in fossil website +locally, use the <b>ui</b> command in place of <b>server</b>. The +<b>ui</b> command starts up a local server too, but it also takes +the additional step of automatically launching your webbrowser and +pointing at the new server.</p> </li> <li><p><b>Setting up a CGI server</b></p> <p>If you have a webserver running on your machine already, you can
Modified www/index.wiki from [635e17dfd6] to [b5ddee628e].
@@ -58,10 +58,12 @@ * The [./concepts.wiki | concepts] behind fossil * [./build.wiki | Building And Installing] * [./quickstart.wiki | Quick Start] guide to using fossil * Fossil supports [./embeddeddoc.wiki | embedded documentation] that is versioned along with project source code. + * A tutorial on [./branching.wiki | branching], what it means and how + to do it using fossil. * The [./selfcheck.wiki | automatic self-check] mechanism helps insure project integrity. * Fossil contains a [./wikitheory.wiki | built-in wiki]. * There is a [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list]