Fossil SCM
Editing pass on the branching.wiki doc. Mostly grammar and clarity improvements, but also added some links to other docs and made some pure additions.
Commit
f8d210aa1c150d13d6ca9d58abf9cec461e4b8c43534e8a6096d617d10c4a956
Parent
0d1db48f926e987…
1 file changed
+121
-87
+121
-87
| --- www/branching.wiki | ||
| +++ www/branching.wiki | ||
| @@ -27,11 +27,11 @@ | ||
| 27 | 27 | and 2 are both <i>ancestors</i> of 3. |
| 28 | 28 | |
| 29 | 29 | <h2 id="dag">DAGs</h2> |
| 30 | 30 | |
| 31 | 31 | The graph of check-ins is a |
| 32 | -[http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph] | |
| 32 | +[http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph], | |
| 33 | 33 | commonly shortened to <i>DAG</i>. Check-in 1 is the <i>root</i> of the DAG |
| 34 | 34 | since it has no ancestors. Check-in 4 is a <i>leaf</i> of the DAG since |
| 35 | 35 | it has no descendants. (We will give a more precise definition later of |
| 36 | 36 | "leaf.") |
| 37 | 37 | |
| @@ -46,92 +46,108 @@ | ||
| 46 | 46 | </td></tr></table> |
| 47 | 47 | |
| 48 | 48 | The graph in Figure 2 has two leaves: check-ins 3 and 4. Check-in 2 has |
| 49 | 49 | two children, check-ins 3 and 4. We call this state a <i>fork</i>. |
| 50 | 50 | |
| 51 | -Fossil tries to prevent forks. Suppose two programmers named Alice and | |
| 51 | +Fossil tries to prevent forks, primarily through its | |
| 52 | +"[./concepts.wiki#workflow | autosync]" mechanism. | |
| 53 | + | |
| 54 | +Suppose two programmers named Alice and | |
| 52 | 55 | Bob are each editing check-in 2 separately. Alice finishes her edits |
| 53 | -first and commits her changes, resulting in check-in 3. Later, when Bob | |
| 56 | +and commits her changes first, resulting in check-in 3. When Bob later | |
| 54 | 57 | attempts to commit his changes, Fossil verifies that check-in 2 is still |
| 55 | 58 | a leaf. Fossil sees that check-in 3 has occurred and aborts Bob's commit |
| 56 | 59 | attempt with a message "would fork." This allows Bob to do a "fossil |
| 57 | -update" which pulls in Alice's changes, merging them into his own | |
| 60 | +update" to pull in Alice's changes, merging them into his own | |
| 58 | 61 | changes. After merging, Bob commits check-in 4 as a child of check-in 3. |
| 59 | 62 | The result is a linear graph as shown in Figure 1. This is how CVS |
| 60 | -works. This is also how Fossil works in [./concepts.wiki#workflow | | |
| 61 | -"autosync"] mode. | |
| 62 | - | |
| 63 | -But perhaps Bob is off-network when he does his commit, so he | |
| 64 | -has no way of knowing that Alice has already committed her changes. | |
| 65 | -Or, it could be that Bob has turned off "autosync" mode in Fossil. Or, | |
| 66 | -maybe Bob just doesn't want to merge in Alice's changes before he has | |
| 67 | -saved his own, so he forces the commit to occur using the "--allow-fork" | |
| 68 | -option to the <b>fossil commit</b> command. For any of these reasons, | |
| 69 | -two commits against check-in 2 have occurred and now the DAG has two leaves. | |
| 70 | - | |
| 71 | -So which version of the project is the "latest" in the sense of having | |
| 72 | -the most features and the most bug fixes? When there is more than | |
| 73 | -one leaf in the graph, you don't really know, so we like to have | |
| 74 | -check-in graphs with a single leaf. | |
| 63 | +works. This is also how Fossil works in autosync mode. | |
| 64 | + | |
| 65 | +But perhaps Bob is off-network when he does his commit, so he has no way | |
| 66 | +of knowing that Alice has already committed her changes. Or, it could | |
| 67 | +be that Bob has turned off "autosync" mode in Fossil. Or, maybe Bob | |
| 68 | +just doesn't want to merge in Alice's changes before he has saved his | |
| 69 | +own, so he forces the commit to occur using the "--allow-fork" option to | |
| 70 | +the <b>[/help?cmd=commit | fossil commit]</b> command. For any of these | |
| 71 | +reasons, two commits against check-in 2 have occurred, so the DAG now | |
| 72 | +has two leaves. | |
| 73 | + | |
| 74 | +In such a condition, a person working with this repository has a | |
| 75 | +dilemma: which version of the project is the "latest" in the sense of | |
| 76 | +having the most features and the most bug fixes? When there is more | |
| 77 | +than one leaf in the graph, you don't really know, which is why we | |
| 78 | +would ideally prefer to have linear check-in graphs. | |
| 75 | 79 | |
| 76 | 80 | Fossil resolves such problems using the check-in time on the leaves to |
| 77 | 81 | decide which leaf to use as the parent of new leaves. When a branch is |
| 78 | 82 | forked as in Figure 2, Fossil will choose check-in 4 as the parent for a |
| 79 | 83 | later check-in 5, but <i>only</i> if it has sync'd that check-in down |
| 80 | 84 | into the local repository. If autosync is disabled or the user is |
| 81 | -off-network when that fifth check-in occurs, so that check-in 3 is the | |
| 85 | +off-network when that fifth check-in occurs so that check-in 3 is the | |
| 82 | 86 | latest on that branch at the time within that clone of the repository, |
| 83 | -Fossil will make check-in 3 the parent of check-in 5! | |
| 87 | +Fossil will make check-in 3 the parent of check-in 5! We show practical | |
| 88 | +consequences of this [#bad-fork | later in this article]. | |
| 84 | 89 | |
| 85 | 90 | Fossil also uses a forked branch's leaf check-in timestamps when |
| 86 | 91 | checking out that branch: it gives you the fork with the latest |
| 87 | 92 | check-in, which in turn selects which parent your next check-in will be |
| 88 | 93 | a child of. This situation means development on that branch can fork |
| 89 | 94 | into two independent lines of development, based solely on which branch |
| 90 | -tip is newer at the time the next user starts his work on it. Because | |
| 91 | -of this, we strongly recommend that you do not intentionally create | |
| 92 | -forks on long-lived shared working branches with "--allow-fork". (Prime | |
| 93 | -example: trunk.) | |
| 95 | +tip is newer at the time the next user starts his work on it. | |
| 96 | + | |
| 97 | +Because of these potential problems, we strongly recommend that you do | |
| 98 | +not intentionally create forks on long-lived shared working branches | |
| 99 | +with "--allow-fork". (Prime example: trunk.) The inverse case — | |
| 100 | +intentional forks on short-lived single-developer branches — is far | |
| 101 | +easier to justify, since presumably the lone developer is never confused | |
| 102 | +about why there are two or more leaves on that branch. Further | |
| 103 | +justifications for intentional forking are [#forking | given below]. | |
| 94 | 104 | |
| 95 | 105 | Let us return to Figure 2. To resolve such situations before they can |
| 96 | -become a real problem, Alice can use the <b>fossil merge</b> command to | |
| 97 | -merge Bob's changes into her local copy of check-in 3. Then she can | |
| 98 | -commit the results as check-in 5. This results in a DAG as shown in | |
| 106 | +become a real problem, Alice can use the <b>[/help?cmd=merge | fossil | |
| 107 | +merge]</b> command to merge Bob's changes into her local copy of | |
| 108 | +check-in 3. Without arguments, that command merges all leaves on the | |
| 109 | +current branch. Alice can then verify that the merge is sensible and if | |
| 110 | +so, commit the results as check-in 5. This results in a DAG as shown in | |
| 99 | 111 | Figure 3. |
| 100 | 112 | |
| 101 | 113 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 102 | 114 | <tr><td align="center"> |
| 103 | 115 | <img src="branch03.svg"><br> |
| 104 | 116 | Figure 3 |
| 105 | 117 | </td></tr></table> |
| 106 | 118 | |
| 107 | 119 | Check-in 5 is a child of check-in 3 because it was created by editing |
| 108 | -check-in 3. But check-in 5 also inherits the changes from check-in 4 by | |
| 109 | -virtue of the merge. So we say that check-in 5 is a <i>merge child</i> | |
| 120 | +check-in 3, but since check-in 5 also inherits the changes from check-in 4 by | |
| 121 | +virtue of the merge, we say that check-in 5 is a <i>merge child</i> | |
| 110 | 122 | of check-in 4 and that it is a <i>direct child</i> of check-in 3. |
| 111 | 123 | The graph is now back to a single leaf, check-in 5. |
| 112 | 124 | |
| 113 | 125 | We have already seen that if Fossil is in autosync mode then Bob would |
| 114 | 126 | have been warned about the potential fork the first time he tried to |
| 115 | 127 | commit check-in 4. If Bob had updated his local check-out to merge in |
| 116 | -Alice's check-in 3 changes, then committed, then the fork would have | |
| 128 | +Alice's check-in 3 changes, then committed, the fork would have | |
| 117 | 129 | never occurred. The resulting graph would have been linear, as shown |
| 118 | 130 | in Figure 1. |
| 119 | 131 | |
| 120 | -Realize that the graph of Figure 1 is a subset of Figure 3. Hold your | |
| 121 | -hand over the check-in 4 circle of Figure 3 and then Figure 3 looks | |
| 122 | -exactly like Figure 1, except that the leaf has a different check-in | |
| 123 | -number, but that is just a notational difference — the two check-ins | |
| 124 | -have exactly the same content. In other words, Figure 3 is really a | |
| 132 | +Realize that the graph of Figure 1 is a subset of Figure 3. If you hold your | |
| 133 | +hand over the ④ in Figure 3, it looks | |
| 134 | +exactly like Figure 1 except that the leaf has a different check-in | |
| 135 | +number. That is just a notational difference: the two check-ins | |
| 136 | +have exactly the same content. | |
| 137 | + | |
| 138 | +Inversely, Figure 3 is a | |
| 125 | 139 | superset of Figure 1. The check-in 4 of Figure 3 captures additional |
| 126 | 140 | state which is omitted from Figure 1. Check-in 4 of Figure 3 holds a |
| 127 | 141 | copy of Bob's local checkout before he merged in Alice's changes. That |
| 128 | 142 | snapshot of Bob's changes, which is independent of Alice's changes, is |
| 129 | -omitted from Figure 1. Some people say that the approach taken in | |
| 143 | +omitted from Figure 1. | |
| 144 | + | |
| 145 | +Some people say that the development approach taken in | |
| 130 | 146 | Figure 3 is better because it preserves this extra intermediate state. |
| 131 | 147 | Others say that the approach taken in Figure 1 is better because it is |
| 132 | -much easier to visualize a linear line of development and because the | |
| 148 | +much easier to visualize linear development and because the | |
| 133 | 149 | merging happens automatically instead of as a separate manual step. We |
| 134 | 150 | will not take sides in that debate. We will simply point out that |
| 135 | 151 | Fossil enables you to do it either way. |
| 136 | 152 | |
| 137 | 153 | <h2 id="branching">The Alternative to Forking: Branching</h2> |
| @@ -144,38 +160,32 @@ | ||
| 144 | 160 | development and another leaf that is the latest version that has been |
| 145 | 161 | tested. |
| 146 | 162 | When multiple leaves are desirable, we call this <i>branching</i> |
| 147 | 163 | instead of <i>forking</i>: |
| 148 | 164 | |
| 149 | -<blockquote> | |
| 150 | -<b>Key Distinction:</b> A branch is a <i>named, intentional</i> fork. | |
| 151 | -</blockquote> | |
| 152 | - | |
| 153 | -Forks <i>may</i> be intentional, but most of the time, they're accidental. | |
| 154 | - | |
| 155 | 165 | Figure 4 shows an example of a project where there are two branches, one |
| 156 | 166 | for development work and another for testing. |
| 157 | 167 | |
| 158 | 168 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 159 | 169 | <tr><td align="center"> |
| 160 | 170 | <img src="branch04.svg"><br> |
| 161 | 171 | Figure 4 |
| 162 | 172 | </td></tr></table> |
| 163 | 173 | |
| 164 | -The hypothetical scenario of Figure 4 is this: The project starts and | |
| 174 | +Figure 4 diagrams the following scenario: the project starts and | |
| 165 | 175 | progresses to a point where (at check-in 2) |
| 166 | 176 | it is ready to enter testing for its first release. |
| 167 | 177 | In a real project, of course, there might be hundreds or thousands of |
| 168 | 178 | check-ins before a project reaches this point, but for simplicity of |
| 169 | 179 | presentation we will say that the project is ready after check-in 2. |
| 170 | 180 | The project then splits into two branches that are used by separate |
| 171 | 181 | teams. The testing team, using the blue branch, finds and fixes a few |
| 172 | -bugs. This is shown by check-ins 6 and 9. Meanwhile the development | |
| 182 | +bugs with check-ins 6 and 9. Meanwhile, the development | |
| 173 | 183 | team, working on the top uncolored branch, |
| 174 | 184 | is busy adding features for the second |
| 175 | 185 | release. Of course, the development team would like to take advantage of |
| 176 | -the bug fixes implemented by the testing team. So periodically, the | |
| 186 | +the bug fixes implemented by the testing team, so periodically the | |
| 177 | 187 | changes in the test branch are merged into the dev branch. This is |
| 178 | 188 | shown by the dashed merge arrows between check-ins 6 and 7 and between |
| 179 | 189 | check-ins 9 and 10. |
| 180 | 190 | |
| 181 | 191 | In both Figures 2 and 4, check-in 2 has two children. In Figure 2, |
| @@ -182,29 +192,46 @@ | ||
| 182 | 192 | we call this a "fork." In diagram 4, we call it a "branch." What is |
| 183 | 193 | the difference? As far as the internal Fossil data structures are |
| 184 | 194 | concerned, there is no difference. The distinction is in the intent. |
| 185 | 195 | In Figure 2, the fact that check-in 2 has multiple children is an |
| 186 | 196 | accident that stems from concurrent development. In Figure 4, giving |
| 187 | -check-in 2 multiple children is a deliberate act. So, to a good | |
| 197 | +check-in 2 multiple children is a deliberate act. To a good | |
| 188 | 198 | approximation, we define forking to be by accident and branching to |
| 189 | 199 | be by intent. Apart from that, they are the same. |
| 200 | + | |
| 201 | +When the fork is intentional, it helps humans to understand what is | |
| 202 | +going on if we <i>name</i> the forks. This is not essential to Fossil's | |
| 203 | +internal data model, but humans have trouble working with long-lived | |
| 204 | +branches identified only by the commit ID currently at its tip, being a | |
| 205 | +long string of hex digits. Therefore, Fossil conflates two concepts: | |
| 206 | +branching as intentional forking and the naming of forks as branches. | |
| 207 | +They are in fact separate concepts, but since Fossil is intended to be | |
| 208 | +used primarily by humans, we combine them in Fossil's human user | |
| 209 | +interfaces. | |
| 210 | + | |
| 211 | +<blockquote> | |
| 212 | +<b>Key Distinction:</b> A branch is a <i>named, intentional</i> fork. | |
| 213 | +</blockquote> | |
| 214 | + | |
| 215 | +Unnamed forks <i>may</i> be intentional, but most of the time, they're | |
| 216 | +accidental and left unnamed. | |
| 190 | 217 | |
| 191 | 218 | Fossil offers two primary ways to create named, intentional forks, |
| 192 | 219 | a.k.a. branches. First: |
| 193 | 220 | |
| 194 | 221 | <pre> |
| 195 | 222 | $ fossil commit --branch my-new-branch-name |
| 196 | 223 | </pre> |
| 197 | 224 | |
| 198 | 225 | This is the method we recommend for most cases: it creates a branch as |
| 199 | -part of a checkin using the version in the current checkout directory | |
| 226 | +part of a check-in using the version in the current checkout directory | |
| 200 | 227 | as its basis. (This is normally the tip of the current branch, though |
| 201 | -it doesn't have to be. You can create a branch from an ancestor checkin | |
| 228 | +it doesn't have to be. You can create a branch from an ancestor check-in | |
| 202 | 229 | on a branch as well.) After making this branch-creating |
| 203 | -checkin, your local working directory is switched to that branch, so | |
| 204 | -that further checkins occur on that branch as well, as children of the | |
| 205 | -tip checkin on that branch. | |
| 230 | +check-in, your local working directory is switched to that branch, so | |
| 231 | +that further check-ins occur on that branch as well, as children of the | |
| 232 | +tip check-in on that branch. | |
| 206 | 233 | |
| 207 | 234 | The second, more complicated option is: |
| 208 | 235 | |
| 209 | 236 | <pre> |
| 210 | 237 | $ fossil branch new my-new-branch-name trunk |
| @@ -212,34 +239,36 @@ | ||
| 212 | 239 | $ fossil commit |
| 213 | 240 | </pre> |
| 214 | 241 | |
| 215 | 242 | Not only is this three commands instead of one, the first of which is |
| 216 | 243 | longer than the entire simpler command above, you must give the second command |
| 217 | -before creating any checkins, because until you do, your local working | |
| 244 | +before creating any check-ins, because until you do, your local working | |
| 218 | 245 | directory remains on the same branch it was on at the time you issued |
| 219 | 246 | the command, so that the commit would otherwise put the new material on |
| 220 | 247 | the original branch instead of the new one. |
| 221 | 248 | |
| 222 | 249 | In addition to those problems, the second method is a violation of the |
| 223 | 250 | [https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it|YAGNI |
| 224 | 251 | Principle]. We recommend that you wait until you actually need the |
| 225 | -branch and create it using the first command above. | |
| 252 | +branch before you create it using the first command above. | |
| 226 | 253 | |
| 227 | -(Keep in mind that trunk is just another branch in Fossil. It is simply | |
| 228 | -the default branch name for the first checkin and every checkin made as | |
| 254 | +The "trunk" is just another named branch in Fossil. It is simply | |
| 255 | +the default branch name for the first check-in and every check-in made as | |
| 229 | 256 | one of its direct descendants. It is special only in that it is Fossil's |
| 230 | -default when it has no better idea of which branch you mean.) | |
| 257 | +default when it has no better idea of which branch you mean. | |
| 231 | 258 | |
| 232 | 259 | |
| 233 | 260 | <h2 id="forking">Justifications For Forking</h2> |
| 234 | 261 | |
| 235 | 262 | The primary cases where forking is justified over branching are all when |
| 236 | 263 | it is done purely in software in order to avoid losing information: |
| 237 | 264 | |
| 238 | 265 | <ol> |
| 239 | 266 | <li><p id="offline">By Fossil itself when two users check in children to the same |
| 240 | - leaf of a branch, as in Figure 2. If the fork occurs because | |
| 267 | + leaf of a branch, as in Figure 2. | |
| 268 | + <br><br> | |
| 269 | + If the fork occurs because | |
| 241 | 270 | autosync is disabled on one or both of the repositories or because |
| 242 | 271 | the user doing the check-in has no network connection at the moment |
| 243 | 272 | of the commit, Fossil has no way of knowing that it is creating a |
| 244 | 273 | fork until the two repositories are later synchronized.</p></li> |
| 245 | 274 | |
| @@ -250,11 +279,11 @@ | ||
| 250 | 279 | negotiation; syncs don't automatically propagate up the clone tree |
| 251 | 280 | beyond that. Because of that, if you have a master repository and |
| 252 | 281 | Alice clones it, then Bobby clones from Alice's repository, a |
| 253 | 282 | check-in by Bobby that autosyncs with Alice's repo will <i>not</i> |
| 254 | 283 | also autosync with the master repo. The master doesn't get a copy of |
| 255 | - Bobby's checkin until Alice <i>separately</i> syncs with the master. | |
| 284 | + Bobby's check-in until Alice <i>separately</i> syncs with the master. | |
| 256 | 285 | If Carol cloned from the master repo and checks something in that |
| 257 | 286 | creates a fork relative to Bobby's check-in, the master repo won't |
| 258 | 287 | know about that fork until Alice syncs her repo with the master. |
| 259 | 288 | Even then, realize that Carol still won't know about the fork until |
| 260 | 289 | she subsequently syncs with the master repo. |
| @@ -262,40 +291,44 @@ | ||
| 262 | 291 | One way to deal with this is to just accept it as a fact of using a |
| 263 | 292 | [https://en.wikipedia.org/wiki/Distributed_version_control|Distributed |
| 264 | 293 | Version Control System] like Fossil. |
| 265 | 294 | <br><br> |
| 266 | 295 | Another option, which we recommend you consider carefully, is to |
| 267 | - make it a local policy that checkins be made only against the master | |
| 296 | + make it a local policy that check-ins be made only directly against the master | |
| 268 | 297 | repo or one of its immediate child clones so that the autosync |
| 269 | - algorithm can do its job most effectively; any clones deeper than | |
| 298 | + algorithm can do its job most effectively. Any clones deeper than | |
| 270 | 299 | that should be treated as read-only and thus get a copy of the new |
| 271 | 300 | state of the world only once these central repos have negotiated |
| 272 | 301 | that new state. This policy avoids a class of inadvertent fork you |
| 273 | 302 | might not need to tolerate. Since [#bad-fork|forks on long-lived |
| 274 | 303 | shared working branches can end up dividing a team's development |
| 275 | 304 | effort], a team may easily justify this restriction on distributed |
| 276 | 305 | cloning.</p></li> |
| 277 | 306 | |
| 278 | - <li><p id="automation">You've automated Fossil (e.g. with a shell script) and | |
| 279 | - forking is a possibility, so you write <b>fossil commit | |
| 280 | - --allow-fork</b> commands to prevent Fossil from refusing the | |
| 281 | - check-in because it would create a fork. It's better to write such | |
| 282 | - a script to detect this condition and cope with it (e.g. <b>fossil | |
| 283 | - update</b>) but if the alternative is losing information, you may | |
| 284 | - feel justified in creating forks that an interactive user must later | |
| 285 | - clean up with <b>fossil merge</b> commands.</p></li> | |
| 307 | + <li><p id="automation">You've automated Fossil, so you use | |
| 308 | + <b>fossil commit --allow-fork</b> commands to prevent Fossil from | |
| 309 | + refusing the check-in simply because it would create a fork. | |
| 310 | + <br><br> | |
| 311 | + If you are writing such a tool — e.g. a shell script to make | |
| 312 | + multiple manipulations on a Fossil repo — it's better to make it | |
| 313 | + smart enough to detect this condition and cope with it, such as | |
| 314 | + by making a call to <b>[/help?cmd=update | fossil update]</b> | |
| 315 | + and checking for a merge conflict. That said, if the alternative is | |
| 316 | + losing information, you may feel justified in creating forks that an | |
| 317 | + interactive user must later manually clean up with <b>fossil merge</b> | |
| 318 | + commands.</p></li> | |
| 286 | 319 | </ol> |
| 287 | 320 | |
| 288 | 321 | That leaves only one case where we can recommend use of "--allow-fork" |
| 289 | -by interactive users: when you're working on | |
| 290 | -a personal branch so that creating a dual-tipped branch isn't going to | |
| 291 | -cause any other user an inconvenience or risk forking the development. | |
| 292 | -Only one developer is involved, and the fork may be short-lived, so | |
| 293 | -there is no risk of [#bad-fork|inadvertently forking the overall development effort]. | |
| 294 | -This is a good alternative to branching when you just need to | |
| 295 | -temporarily fork the branch's development. It avoids cluttering the | |
| 296 | -global branch namespace with short-lived temporary named branches. | |
| 322 | +by interactive users: when you're working on a personal branch so that | |
| 323 | +creating a dual-tipped branch isn't going to cause any other user an | |
| 324 | +inconvenience or risk [#bad-fork | inadvertently forking the development | |
| 325 | +effort]. In such a case, the lone developer working on that branch is | |
| 326 | +not confused, since the fork in development is intentional. Sometimes it | |
| 327 | +simply makes no sense to bother creating a name, cluttering the global | |
| 328 | +branch namespace, simply to convert an intentional fork into a "branch." | |
| 329 | +This is especially the case when the fork is short-lived. | |
| 297 | 330 | |
| 298 | 331 | There's a common generalization of that case: you're a solo developer, |
| 299 | 332 | so that the problems with branching vs forking simply don't matter. In |
| 300 | 333 | that case, feel free to use "--allow-fork" as much as you like. |
| 301 | 334 | |
| @@ -402,11 +435,11 @@ | ||
| 402 | 435 | All users on this diagram start out with the same view of the |
| 403 | 436 | repository, cloned from the same master repo, and all of them are |
| 404 | 437 | working toward their shared vision of a unified future. |
| 405 | 438 | |
| 406 | 439 | All users, except possibly Alan, start out with the same two initial |
| 407 | -checkins in their local working clones, 1 & 2. It might be that Alan | |
| 440 | +check-ins in their local working clones, 1 & 2. It might be that Alan | |
| 408 | 441 | starts out with only check-in 1 in his local clone, but we'll deal with |
| 409 | 442 | that detail later. |
| 410 | 443 | |
| 411 | 444 | It doesn't matter which branch this happy team is working on, only that |
| 412 | 445 | our example makes the most sense if you think of it as a long-lived shared |
| @@ -434,17 +467,17 @@ | ||
| 434 | 467 | to that branch with a <b>fossil update $BRANCH</b> command. (There is an |
| 435 | 468 | implicit autosync in that command, if the option was enabled at the |
| 436 | 469 | time of the update.)</p></li> |
| 437 | 470 | |
| 438 | 471 | <li><p>The same thing, only in a fresh checkout directory with a |
| 439 | - <b>fossil open $REPO $BRANCH</b> command.</p></li> | |
| 472 | + <b>[/help?cmd=open | fossil open $REPO $BRANCH]</b> command.</p></li> | |
| 440 | 473 | |
| 441 | 474 | <li><p>Alan makes his check-in 3 while Betty has check-in 1 or 2 as |
| 442 | 475 | the tip in her local clone, but because she's working with an |
| 443 | 476 | autosync'd connection to the same upstream repository as Alan, on |
| 444 | 477 | attempting what will become check-in 4, she gets the "would fork" |
| 445 | - message from <b>fossil ci</b>, so she dutifully updates her clone | |
| 478 | + message from <b>fossil commit</b>, so she dutifully updates her clone | |
| 446 | 479 | and tries again, moving her work to be a child of the new tip, |
| 447 | 480 | check-in 3. (If she doesn't update, she creates a <i>second</i> |
| 448 | 481 | fork, which simply complicates matters beyond what we need here for |
| 449 | 482 | our illustration.)</p></li> |
| 450 | 483 | </ol> |
| @@ -575,26 +608,27 @@ | ||
| 575 | 608 | <h3 id="unique">Branch Names Need Not Be Unique</h3> |
| 576 | 609 | |
| 577 | 610 | Fossil does not require that branch names be unique, as in some VCSes, |
| 578 | 611 | most notably Git. Just as with unnamed branches (which we call forks) |
| 579 | 612 | Fossil resolves such ambiguities using the timestamps on the latest |
| 580 | -checkin in each branch. If you have two branches named "foo" and you say | |
| 581 | -<b>fossil up foo</b>, you get the tip of the "foo" branch with the most | |
| 582 | -recent checkin. | |
| 613 | +check-in in each branch. If you have two branches named "foo" and you say | |
| 614 | +<b>fossil update foo</b>, you get the tip of the "foo" branch with the most | |
| 615 | +recent check-in. | |
| 583 | 616 | |
| 584 | 617 | This fact is helpful because it means you can reuse branch names, which |
| 585 | 618 | is especially useful with utility branches. There are several of these |
| 586 | 619 | in the SQLite and Fossil repositories: "broken-build," "declined," |
| 587 | 620 | "mistake," etc. As you might guess from these names, such branch names |
| 588 | 621 | are used in renaming the tip of one branch to shunt it off away from the |
| 589 | -mainline of that branch due to some human error. (See <b>fossil | |
| 590 | -amend</b> and the Fossil UI checkin amendment features.) This is a | |
| 622 | +mainline of that branch due to some human error. (See | |
| 623 | +<b>[/help?cmd=amend | fossil | |
| 624 | +amend]</b> and the Fossil UI check-in amendment features.) This is a | |
| 591 | 625 | workaround for Fossil's [./shunning.wiki|normal inability to forget |
| 592 | 626 | history]: we usually don't want to actually <i>remove</i> history, but |
| 593 | 627 | would like to sometimes set some of it aside under a new label. |
| 594 | 628 | |
| 595 | 629 | Because some VCSes can't cope with duplicate branch names, Fossil |
| 596 | 630 | collapses such names down on export using the same time stamp based |
| 597 | -arbitration logic, so that only the branch with the newest checkin gets | |
| 631 | +arbitration logic, so that only the branch with the newest check-in gets | |
| 598 | 632 | the branch name in the export. |
| 599 | 633 | |
| 600 | 634 | All of the above is true of tags in general, not just branches. |
| 601 | 635 |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | and 2 are both <i>ancestors</i> of 3. |
| 28 | |
| 29 | <h2 id="dag">DAGs</h2> |
| 30 | |
| 31 | The graph of check-ins is a |
| 32 | [http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph] |
| 33 | commonly shortened to <i>DAG</i>. Check-in 1 is the <i>root</i> of the DAG |
| 34 | since it has no ancestors. Check-in 4 is a <i>leaf</i> of the DAG since |
| 35 | it has no descendants. (We will give a more precise definition later of |
| 36 | "leaf.") |
| 37 | |
| @@ -46,92 +46,108 @@ | |
| 46 | </td></tr></table> |
| 47 | |
| 48 | The graph in Figure 2 has two leaves: check-ins 3 and 4. Check-in 2 has |
| 49 | two children, check-ins 3 and 4. We call this state a <i>fork</i>. |
| 50 | |
| 51 | Fossil tries to prevent forks. Suppose two programmers named Alice and |
| 52 | Bob are each editing check-in 2 separately. Alice finishes her edits |
| 53 | first and commits her changes, resulting in check-in 3. Later, when Bob |
| 54 | attempts to commit his changes, Fossil verifies that check-in 2 is still |
| 55 | a leaf. Fossil sees that check-in 3 has occurred and aborts Bob's commit |
| 56 | attempt with a message "would fork." This allows Bob to do a "fossil |
| 57 | update" which pulls in Alice's changes, merging them into his own |
| 58 | changes. After merging, Bob commits check-in 4 as a child of check-in 3. |
| 59 | The result is a linear graph as shown in Figure 1. This is how CVS |
| 60 | works. This is also how Fossil works in [./concepts.wiki#workflow | |
| 61 | "autosync"] mode. |
| 62 | |
| 63 | But perhaps Bob is off-network when he does his commit, so he |
| 64 | has no way of knowing that Alice has already committed her changes. |
| 65 | Or, it could be that Bob has turned off "autosync" mode in Fossil. Or, |
| 66 | maybe Bob just doesn't want to merge in Alice's changes before he has |
| 67 | saved his own, so he forces the commit to occur using the "--allow-fork" |
| 68 | option to the <b>fossil commit</b> command. For any of these reasons, |
| 69 | two commits against check-in 2 have occurred and now the DAG has two leaves. |
| 70 | |
| 71 | So which version of the project is the "latest" in the sense of having |
| 72 | the most features and the most bug fixes? When there is more than |
| 73 | one leaf in the graph, you don't really know, so we like to have |
| 74 | check-in graphs with a single leaf. |
| 75 | |
| 76 | Fossil resolves such problems using the check-in time on the leaves to |
| 77 | decide which leaf to use as the parent of new leaves. When a branch is |
| 78 | forked as in Figure 2, Fossil will choose check-in 4 as the parent for a |
| 79 | later check-in 5, but <i>only</i> if it has sync'd that check-in down |
| 80 | into the local repository. If autosync is disabled or the user is |
| 81 | off-network when that fifth check-in occurs, so that check-in 3 is the |
| 82 | latest on that branch at the time within that clone of the repository, |
| 83 | Fossil will make check-in 3 the parent of check-in 5! |
| 84 | |
| 85 | Fossil also uses a forked branch's leaf check-in timestamps when |
| 86 | checking out that branch: it gives you the fork with the latest |
| 87 | check-in, which in turn selects which parent your next check-in will be |
| 88 | a child of. This situation means development on that branch can fork |
| 89 | into two independent lines of development, based solely on which branch |
| 90 | tip is newer at the time the next user starts his work on it. Because |
| 91 | of this, we strongly recommend that you do not intentionally create |
| 92 | forks on long-lived shared working branches with "--allow-fork". (Prime |
| 93 | example: trunk.) |
| 94 | |
| 95 | Let us return to Figure 2. To resolve such situations before they can |
| 96 | become a real problem, Alice can use the <b>fossil merge</b> command to |
| 97 | merge Bob's changes into her local copy of check-in 3. Then she can |
| 98 | commit the results as check-in 5. This results in a DAG as shown in |
| 99 | Figure 3. |
| 100 | |
| 101 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 102 | <tr><td align="center"> |
| 103 | <img src="branch03.svg"><br> |
| 104 | Figure 3 |
| 105 | </td></tr></table> |
| 106 | |
| 107 | Check-in 5 is a child of check-in 3 because it was created by editing |
| 108 | check-in 3. But check-in 5 also inherits the changes from check-in 4 by |
| 109 | virtue of the merge. So we say that check-in 5 is a <i>merge child</i> |
| 110 | of check-in 4 and that it is a <i>direct child</i> of check-in 3. |
| 111 | The graph is now back to a single leaf, check-in 5. |
| 112 | |
| 113 | We have already seen that if Fossil is in autosync mode then Bob would |
| 114 | have been warned about the potential fork the first time he tried to |
| 115 | commit check-in 4. If Bob had updated his local check-out to merge in |
| 116 | Alice's check-in 3 changes, then committed, then the fork would have |
| 117 | never occurred. The resulting graph would have been linear, as shown |
| 118 | in Figure 1. |
| 119 | |
| 120 | Realize that the graph of Figure 1 is a subset of Figure 3. Hold your |
| 121 | hand over the check-in 4 circle of Figure 3 and then Figure 3 looks |
| 122 | exactly like Figure 1, except that the leaf has a different check-in |
| 123 | number, but that is just a notational difference — the two check-ins |
| 124 | have exactly the same content. In other words, Figure 3 is really a |
| 125 | superset of Figure 1. The check-in 4 of Figure 3 captures additional |
| 126 | state which is omitted from Figure 1. Check-in 4 of Figure 3 holds a |
| 127 | copy of Bob's local checkout before he merged in Alice's changes. That |
| 128 | snapshot of Bob's changes, which is independent of Alice's changes, is |
| 129 | omitted from Figure 1. Some people say that the approach taken in |
| 130 | Figure 3 is better because it preserves this extra intermediate state. |
| 131 | Others say that the approach taken in Figure 1 is better because it is |
| 132 | much easier to visualize a linear line of development and because the |
| 133 | merging happens automatically instead of as a separate manual step. We |
| 134 | will not take sides in that debate. We will simply point out that |
| 135 | Fossil enables you to do it either way. |
| 136 | |
| 137 | <h2 id="branching">The Alternative to Forking: Branching</h2> |
| @@ -144,38 +160,32 @@ | |
| 144 | development and another leaf that is the latest version that has been |
| 145 | tested. |
| 146 | When multiple leaves are desirable, we call this <i>branching</i> |
| 147 | instead of <i>forking</i>: |
| 148 | |
| 149 | <blockquote> |
| 150 | <b>Key Distinction:</b> A branch is a <i>named, intentional</i> fork. |
| 151 | </blockquote> |
| 152 | |
| 153 | Forks <i>may</i> be intentional, but most of the time, they're accidental. |
| 154 | |
| 155 | Figure 4 shows an example of a project where there are two branches, one |
| 156 | for development work and another for testing. |
| 157 | |
| 158 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 159 | <tr><td align="center"> |
| 160 | <img src="branch04.svg"><br> |
| 161 | Figure 4 |
| 162 | </td></tr></table> |
| 163 | |
| 164 | The hypothetical scenario of Figure 4 is this: The project starts and |
| 165 | progresses to a point where (at check-in 2) |
| 166 | it is ready to enter testing for its first release. |
| 167 | In a real project, of course, there might be hundreds or thousands of |
| 168 | check-ins before a project reaches this point, but for simplicity of |
| 169 | presentation we will say that the project is ready after check-in 2. |
| 170 | The project then splits into two branches that are used by separate |
| 171 | teams. The testing team, using the blue branch, finds and fixes a few |
| 172 | bugs. This is shown by check-ins 6 and 9. Meanwhile the development |
| 173 | team, working on the top uncolored branch, |
| 174 | is busy adding features for the second |
| 175 | release. Of course, the development team would like to take advantage of |
| 176 | the bug fixes implemented by the testing team. So periodically, the |
| 177 | changes in the test branch are merged into the dev branch. This is |
| 178 | shown by the dashed merge arrows between check-ins 6 and 7 and between |
| 179 | check-ins 9 and 10. |
| 180 | |
| 181 | In both Figures 2 and 4, check-in 2 has two children. In Figure 2, |
| @@ -182,29 +192,46 @@ | |
| 182 | we call this a "fork." In diagram 4, we call it a "branch." What is |
| 183 | the difference? As far as the internal Fossil data structures are |
| 184 | concerned, there is no difference. The distinction is in the intent. |
| 185 | In Figure 2, the fact that check-in 2 has multiple children is an |
| 186 | accident that stems from concurrent development. In Figure 4, giving |
| 187 | check-in 2 multiple children is a deliberate act. So, to a good |
| 188 | approximation, we define forking to be by accident and branching to |
| 189 | be by intent. Apart from that, they are the same. |
| 190 | |
| 191 | Fossil offers two primary ways to create named, intentional forks, |
| 192 | a.k.a. branches. First: |
| 193 | |
| 194 | <pre> |
| 195 | $ fossil commit --branch my-new-branch-name |
| 196 | </pre> |
| 197 | |
| 198 | This is the method we recommend for most cases: it creates a branch as |
| 199 | part of a checkin using the version in the current checkout directory |
| 200 | as its basis. (This is normally the tip of the current branch, though |
| 201 | it doesn't have to be. You can create a branch from an ancestor checkin |
| 202 | on a branch as well.) After making this branch-creating |
| 203 | checkin, your local working directory is switched to that branch, so |
| 204 | that further checkins occur on that branch as well, as children of the |
| 205 | tip checkin on that branch. |
| 206 | |
| 207 | The second, more complicated option is: |
| 208 | |
| 209 | <pre> |
| 210 | $ fossil branch new my-new-branch-name trunk |
| @@ -212,34 +239,36 @@ | |
| 212 | $ fossil commit |
| 213 | </pre> |
| 214 | |
| 215 | Not only is this three commands instead of one, the first of which is |
| 216 | longer than the entire simpler command above, you must give the second command |
| 217 | before creating any checkins, because until you do, your local working |
| 218 | directory remains on the same branch it was on at the time you issued |
| 219 | the command, so that the commit would otherwise put the new material on |
| 220 | the original branch instead of the new one. |
| 221 | |
| 222 | In addition to those problems, the second method is a violation of the |
| 223 | [https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it|YAGNI |
| 224 | Principle]. We recommend that you wait until you actually need the |
| 225 | branch and create it using the first command above. |
| 226 | |
| 227 | (Keep in mind that trunk is just another branch in Fossil. It is simply |
| 228 | the default branch name for the first checkin and every checkin made as |
| 229 | one of its direct descendants. It is special only in that it is Fossil's |
| 230 | default when it has no better idea of which branch you mean.) |
| 231 | |
| 232 | |
| 233 | <h2 id="forking">Justifications For Forking</h2> |
| 234 | |
| 235 | The primary cases where forking is justified over branching are all when |
| 236 | it is done purely in software in order to avoid losing information: |
| 237 | |
| 238 | <ol> |
| 239 | <li><p id="offline">By Fossil itself when two users check in children to the same |
| 240 | leaf of a branch, as in Figure 2. If the fork occurs because |
| 241 | autosync is disabled on one or both of the repositories or because |
| 242 | the user doing the check-in has no network connection at the moment |
| 243 | of the commit, Fossil has no way of knowing that it is creating a |
| 244 | fork until the two repositories are later synchronized.</p></li> |
| 245 | |
| @@ -250,11 +279,11 @@ | |
| 250 | negotiation; syncs don't automatically propagate up the clone tree |
| 251 | beyond that. Because of that, if you have a master repository and |
| 252 | Alice clones it, then Bobby clones from Alice's repository, a |
| 253 | check-in by Bobby that autosyncs with Alice's repo will <i>not</i> |
| 254 | also autosync with the master repo. The master doesn't get a copy of |
| 255 | Bobby's checkin until Alice <i>separately</i> syncs with the master. |
| 256 | If Carol cloned from the master repo and checks something in that |
| 257 | creates a fork relative to Bobby's check-in, the master repo won't |
| 258 | know about that fork until Alice syncs her repo with the master. |
| 259 | Even then, realize that Carol still won't know about the fork until |
| 260 | she subsequently syncs with the master repo. |
| @@ -262,40 +291,44 @@ | |
| 262 | One way to deal with this is to just accept it as a fact of using a |
| 263 | [https://en.wikipedia.org/wiki/Distributed_version_control|Distributed |
| 264 | Version Control System] like Fossil. |
| 265 | <br><br> |
| 266 | Another option, which we recommend you consider carefully, is to |
| 267 | make it a local policy that checkins be made only against the master |
| 268 | repo or one of its immediate child clones so that the autosync |
| 269 | algorithm can do its job most effectively; any clones deeper than |
| 270 | that should be treated as read-only and thus get a copy of the new |
| 271 | state of the world only once these central repos have negotiated |
| 272 | that new state. This policy avoids a class of inadvertent fork you |
| 273 | might not need to tolerate. Since [#bad-fork|forks on long-lived |
| 274 | shared working branches can end up dividing a team's development |
| 275 | effort], a team may easily justify this restriction on distributed |
| 276 | cloning.</p></li> |
| 277 | |
| 278 | <li><p id="automation">You've automated Fossil (e.g. with a shell script) and |
| 279 | forking is a possibility, so you write <b>fossil commit |
| 280 | --allow-fork</b> commands to prevent Fossil from refusing the |
| 281 | check-in because it would create a fork. It's better to write such |
| 282 | a script to detect this condition and cope with it (e.g. <b>fossil |
| 283 | update</b>) but if the alternative is losing information, you may |
| 284 | feel justified in creating forks that an interactive user must later |
| 285 | clean up with <b>fossil merge</b> commands.</p></li> |
| 286 | </ol> |
| 287 | |
| 288 | That leaves only one case where we can recommend use of "--allow-fork" |
| 289 | by interactive users: when you're working on |
| 290 | a personal branch so that creating a dual-tipped branch isn't going to |
| 291 | cause any other user an inconvenience or risk forking the development. |
| 292 | Only one developer is involved, and the fork may be short-lived, so |
| 293 | there is no risk of [#bad-fork|inadvertently forking the overall development effort]. |
| 294 | This is a good alternative to branching when you just need to |
| 295 | temporarily fork the branch's development. It avoids cluttering the |
| 296 | global branch namespace with short-lived temporary named branches. |
| 297 | |
| 298 | There's a common generalization of that case: you're a solo developer, |
| 299 | so that the problems with branching vs forking simply don't matter. In |
| 300 | that case, feel free to use "--allow-fork" as much as you like. |
| 301 | |
| @@ -402,11 +435,11 @@ | |
| 402 | All users on this diagram start out with the same view of the |
| 403 | repository, cloned from the same master repo, and all of them are |
| 404 | working toward their shared vision of a unified future. |
| 405 | |
| 406 | All users, except possibly Alan, start out with the same two initial |
| 407 | checkins in their local working clones, 1 & 2. It might be that Alan |
| 408 | starts out with only check-in 1 in his local clone, but we'll deal with |
| 409 | that detail later. |
| 410 | |
| 411 | It doesn't matter which branch this happy team is working on, only that |
| 412 | our example makes the most sense if you think of it as a long-lived shared |
| @@ -434,17 +467,17 @@ | |
| 434 | to that branch with a <b>fossil update $BRANCH</b> command. (There is an |
| 435 | implicit autosync in that command, if the option was enabled at the |
| 436 | time of the update.)</p></li> |
| 437 | |
| 438 | <li><p>The same thing, only in a fresh checkout directory with a |
| 439 | <b>fossil open $REPO $BRANCH</b> command.</p></li> |
| 440 | |
| 441 | <li><p>Alan makes his check-in 3 while Betty has check-in 1 or 2 as |
| 442 | the tip in her local clone, but because she's working with an |
| 443 | autosync'd connection to the same upstream repository as Alan, on |
| 444 | attempting what will become check-in 4, she gets the "would fork" |
| 445 | message from <b>fossil ci</b>, so she dutifully updates her clone |
| 446 | and tries again, moving her work to be a child of the new tip, |
| 447 | check-in 3. (If she doesn't update, she creates a <i>second</i> |
| 448 | fork, which simply complicates matters beyond what we need here for |
| 449 | our illustration.)</p></li> |
| 450 | </ol> |
| @@ -575,26 +608,27 @@ | |
| 575 | <h3 id="unique">Branch Names Need Not Be Unique</h3> |
| 576 | |
| 577 | Fossil does not require that branch names be unique, as in some VCSes, |
| 578 | most notably Git. Just as with unnamed branches (which we call forks) |
| 579 | Fossil resolves such ambiguities using the timestamps on the latest |
| 580 | checkin in each branch. If you have two branches named "foo" and you say |
| 581 | <b>fossil up foo</b>, you get the tip of the "foo" branch with the most |
| 582 | recent checkin. |
| 583 | |
| 584 | This fact is helpful because it means you can reuse branch names, which |
| 585 | is especially useful with utility branches. There are several of these |
| 586 | in the SQLite and Fossil repositories: "broken-build," "declined," |
| 587 | "mistake," etc. As you might guess from these names, such branch names |
| 588 | are used in renaming the tip of one branch to shunt it off away from the |
| 589 | mainline of that branch due to some human error. (See <b>fossil |
| 590 | amend</b> and the Fossil UI checkin amendment features.) This is a |
| 591 | workaround for Fossil's [./shunning.wiki|normal inability to forget |
| 592 | history]: we usually don't want to actually <i>remove</i> history, but |
| 593 | would like to sometimes set some of it aside under a new label. |
| 594 | |
| 595 | Because some VCSes can't cope with duplicate branch names, Fossil |
| 596 | collapses such names down on export using the same time stamp based |
| 597 | arbitration logic, so that only the branch with the newest checkin gets |
| 598 | the branch name in the export. |
| 599 | |
| 600 | All of the above is true of tags in general, not just branches. |
| 601 |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -27,11 +27,11 @@ | |
| 27 | and 2 are both <i>ancestors</i> of 3. |
| 28 | |
| 29 | <h2 id="dag">DAGs</h2> |
| 30 | |
| 31 | The graph of check-ins is a |
| 32 | [http://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic graph], |
| 33 | commonly shortened to <i>DAG</i>. Check-in 1 is the <i>root</i> of the DAG |
| 34 | since it has no ancestors. Check-in 4 is a <i>leaf</i> of the DAG since |
| 35 | it has no descendants. (We will give a more precise definition later of |
| 36 | "leaf.") |
| 37 | |
| @@ -46,92 +46,108 @@ | |
| 46 | </td></tr></table> |
| 47 | |
| 48 | The graph in Figure 2 has two leaves: check-ins 3 and 4. Check-in 2 has |
| 49 | two children, check-ins 3 and 4. We call this state a <i>fork</i>. |
| 50 | |
| 51 | Fossil tries to prevent forks, primarily through its |
| 52 | "[./concepts.wiki#workflow | autosync]" mechanism. |
| 53 | |
| 54 | Suppose two programmers named Alice and |
| 55 | Bob are each editing check-in 2 separately. Alice finishes her edits |
| 56 | and commits her changes first, resulting in check-in 3. When Bob later |
| 57 | attempts to commit his changes, Fossil verifies that check-in 2 is still |
| 58 | a leaf. Fossil sees that check-in 3 has occurred and aborts Bob's commit |
| 59 | attempt with a message "would fork." This allows Bob to do a "fossil |
| 60 | update" to pull in Alice's changes, merging them into his own |
| 61 | changes. After merging, Bob commits check-in 4 as a child of check-in 3. |
| 62 | The result is a linear graph as shown in Figure 1. This is how CVS |
| 63 | works. This is also how Fossil works in autosync mode. |
| 64 | |
| 65 | But perhaps Bob is off-network when he does his commit, so he has no way |
| 66 | of knowing that Alice has already committed her changes. Or, it could |
| 67 | be that Bob has turned off "autosync" mode in Fossil. Or, maybe Bob |
| 68 | just doesn't want to merge in Alice's changes before he has saved his |
| 69 | own, so he forces the commit to occur using the "--allow-fork" option to |
| 70 | the <b>[/help?cmd=commit | fossil commit]</b> command. For any of these |
| 71 | reasons, two commits against check-in 2 have occurred, so the DAG now |
| 72 | has two leaves. |
| 73 | |
| 74 | In such a condition, a person working with this repository has a |
| 75 | dilemma: which version of the project is the "latest" in the sense of |
| 76 | having the most features and the most bug fixes? When there is more |
| 77 | than one leaf in the graph, you don't really know, which is why we |
| 78 | would ideally prefer to have linear check-in graphs. |
| 79 | |
| 80 | Fossil resolves such problems using the check-in time on the leaves to |
| 81 | decide which leaf to use as the parent of new leaves. When a branch is |
| 82 | forked as in Figure 2, Fossil will choose check-in 4 as the parent for a |
| 83 | later check-in 5, but <i>only</i> if it has sync'd that check-in down |
| 84 | into the local repository. If autosync is disabled or the user is |
| 85 | off-network when that fifth check-in occurs so that check-in 3 is the |
| 86 | latest on that branch at the time within that clone of the repository, |
| 87 | Fossil will make check-in 3 the parent of check-in 5! We show practical |
| 88 | consequences of this [#bad-fork | later in this article]. |
| 89 | |
| 90 | Fossil also uses a forked branch's leaf check-in timestamps when |
| 91 | checking out that branch: it gives you the fork with the latest |
| 92 | check-in, which in turn selects which parent your next check-in will be |
| 93 | a child of. This situation means development on that branch can fork |
| 94 | into two independent lines of development, based solely on which branch |
| 95 | tip is newer at the time the next user starts his work on it. |
| 96 | |
| 97 | Because of these potential problems, we strongly recommend that you do |
| 98 | not intentionally create forks on long-lived shared working branches |
| 99 | with "--allow-fork". (Prime example: trunk.) The inverse case — |
| 100 | intentional forks on short-lived single-developer branches — is far |
| 101 | easier to justify, since presumably the lone developer is never confused |
| 102 | about why there are two or more leaves on that branch. Further |
| 103 | justifications for intentional forking are [#forking | given below]. |
| 104 | |
| 105 | Let us return to Figure 2. To resolve such situations before they can |
| 106 | become a real problem, Alice can use the <b>[/help?cmd=merge | fossil |
| 107 | merge]</b> command to merge Bob's changes into her local copy of |
| 108 | check-in 3. Without arguments, that command merges all leaves on the |
| 109 | current branch. Alice can then verify that the merge is sensible and if |
| 110 | so, commit the results as check-in 5. This results in a DAG as shown in |
| 111 | Figure 3. |
| 112 | |
| 113 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 114 | <tr><td align="center"> |
| 115 | <img src="branch03.svg"><br> |
| 116 | Figure 3 |
| 117 | </td></tr></table> |
| 118 | |
| 119 | Check-in 5 is a child of check-in 3 because it was created by editing |
| 120 | check-in 3, but since check-in 5 also inherits the changes from check-in 4 by |
| 121 | virtue of the merge, we say that check-in 5 is a <i>merge child</i> |
| 122 | of check-in 4 and that it is a <i>direct child</i> of check-in 3. |
| 123 | The graph is now back to a single leaf, check-in 5. |
| 124 | |
| 125 | We have already seen that if Fossil is in autosync mode then Bob would |
| 126 | have been warned about the potential fork the first time he tried to |
| 127 | commit check-in 4. If Bob had updated his local check-out to merge in |
| 128 | Alice's check-in 3 changes, then committed, the fork would have |
| 129 | never occurred. The resulting graph would have been linear, as shown |
| 130 | in Figure 1. |
| 131 | |
| 132 | Realize that the graph of Figure 1 is a subset of Figure 3. If you hold your |
| 133 | hand over the ④ in Figure 3, it looks |
| 134 | exactly like Figure 1 except that the leaf has a different check-in |
| 135 | number. That is just a notational difference: the two check-ins |
| 136 | have exactly the same content. |
| 137 | |
| 138 | Inversely, Figure 3 is a |
| 139 | superset of Figure 1. The check-in 4 of Figure 3 captures additional |
| 140 | state which is omitted from Figure 1. Check-in 4 of Figure 3 holds a |
| 141 | copy of Bob's local checkout before he merged in Alice's changes. That |
| 142 | snapshot of Bob's changes, which is independent of Alice's changes, is |
| 143 | omitted from Figure 1. |
| 144 | |
| 145 | Some people say that the development approach taken in |
| 146 | Figure 3 is better because it preserves this extra intermediate state. |
| 147 | Others say that the approach taken in Figure 1 is better because it is |
| 148 | much easier to visualize linear development and because the |
| 149 | merging happens automatically instead of as a separate manual step. We |
| 150 | will not take sides in that debate. We will simply point out that |
| 151 | Fossil enables you to do it either way. |
| 152 | |
| 153 | <h2 id="branching">The Alternative to Forking: Branching</h2> |
| @@ -144,38 +160,32 @@ | |
| 160 | development and another leaf that is the latest version that has been |
| 161 | tested. |
| 162 | When multiple leaves are desirable, we call this <i>branching</i> |
| 163 | instead of <i>forking</i>: |
| 164 | |
| 165 | Figure 4 shows an example of a project where there are two branches, one |
| 166 | for development work and another for testing. |
| 167 | |
| 168 | <table border=1 cellpadding=10 hspace=10 vspace=10 align="center"> |
| 169 | <tr><td align="center"> |
| 170 | <img src="branch04.svg"><br> |
| 171 | Figure 4 |
| 172 | </td></tr></table> |
| 173 | |
| 174 | Figure 4 diagrams the following scenario: the project starts and |
| 175 | progresses to a point where (at check-in 2) |
| 176 | it is ready to enter testing for its first release. |
| 177 | In a real project, of course, there might be hundreds or thousands of |
| 178 | check-ins before a project reaches this point, but for simplicity of |
| 179 | presentation we will say that the project is ready after check-in 2. |
| 180 | The project then splits into two branches that are used by separate |
| 181 | teams. The testing team, using the blue branch, finds and fixes a few |
| 182 | bugs with check-ins 6 and 9. Meanwhile, the development |
| 183 | team, working on the top uncolored branch, |
| 184 | is busy adding features for the second |
| 185 | release. Of course, the development team would like to take advantage of |
| 186 | the bug fixes implemented by the testing team, so periodically the |
| 187 | changes in the test branch are merged into the dev branch. This is |
| 188 | shown by the dashed merge arrows between check-ins 6 and 7 and between |
| 189 | check-ins 9 and 10. |
| 190 | |
| 191 | In both Figures 2 and 4, check-in 2 has two children. In Figure 2, |
| @@ -182,29 +192,46 @@ | |
| 192 | we call this a "fork." In diagram 4, we call it a "branch." What is |
| 193 | the difference? As far as the internal Fossil data structures are |
| 194 | concerned, there is no difference. The distinction is in the intent. |
| 195 | In Figure 2, the fact that check-in 2 has multiple children is an |
| 196 | accident that stems from concurrent development. In Figure 4, giving |
| 197 | check-in 2 multiple children is a deliberate act. To a good |
| 198 | approximation, we define forking to be by accident and branching to |
| 199 | be by intent. Apart from that, they are the same. |
| 200 | |
| 201 | When the fork is intentional, it helps humans to understand what is |
| 202 | going on if we <i>name</i> the forks. This is not essential to Fossil's |
| 203 | internal data model, but humans have trouble working with long-lived |
| 204 | branches identified only by the commit ID currently at its tip, being a |
| 205 | long string of hex digits. Therefore, Fossil conflates two concepts: |
| 206 | branching as intentional forking and the naming of forks as branches. |
| 207 | They are in fact separate concepts, but since Fossil is intended to be |
| 208 | used primarily by humans, we combine them in Fossil's human user |
| 209 | interfaces. |
| 210 | |
| 211 | <blockquote> |
| 212 | <b>Key Distinction:</b> A branch is a <i>named, intentional</i> fork. |
| 213 | </blockquote> |
| 214 | |
| 215 | Unnamed forks <i>may</i> be intentional, but most of the time, they're |
| 216 | accidental and left unnamed. |
| 217 | |
| 218 | Fossil offers two primary ways to create named, intentional forks, |
| 219 | a.k.a. branches. First: |
| 220 | |
| 221 | <pre> |
| 222 | $ fossil commit --branch my-new-branch-name |
| 223 | </pre> |
| 224 | |
| 225 | This is the method we recommend for most cases: it creates a branch as |
| 226 | part of a check-in using the version in the current checkout directory |
| 227 | as its basis. (This is normally the tip of the current branch, though |
| 228 | it doesn't have to be. You can create a branch from an ancestor check-in |
| 229 | on a branch as well.) After making this branch-creating |
| 230 | check-in, your local working directory is switched to that branch, so |
| 231 | that further check-ins occur on that branch as well, as children of the |
| 232 | tip check-in on that branch. |
| 233 | |
| 234 | The second, more complicated option is: |
| 235 | |
| 236 | <pre> |
| 237 | $ fossil branch new my-new-branch-name trunk |
| @@ -212,34 +239,36 @@ | |
| 239 | $ fossil commit |
| 240 | </pre> |
| 241 | |
| 242 | Not only is this three commands instead of one, the first of which is |
| 243 | longer than the entire simpler command above, you must give the second command |
| 244 | before creating any check-ins, because until you do, your local working |
| 245 | directory remains on the same branch it was on at the time you issued |
| 246 | the command, so that the commit would otherwise put the new material on |
| 247 | the original branch instead of the new one. |
| 248 | |
| 249 | In addition to those problems, the second method is a violation of the |
| 250 | [https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it|YAGNI |
| 251 | Principle]. We recommend that you wait until you actually need the |
| 252 | branch before you create it using the first command above. |
| 253 | |
| 254 | The "trunk" is just another named branch in Fossil. It is simply |
| 255 | the default branch name for the first check-in and every check-in made as |
| 256 | one of its direct descendants. It is special only in that it is Fossil's |
| 257 | default when it has no better idea of which branch you mean. |
| 258 | |
| 259 | |
| 260 | <h2 id="forking">Justifications For Forking</h2> |
| 261 | |
| 262 | The primary cases where forking is justified over branching are all when |
| 263 | it is done purely in software in order to avoid losing information: |
| 264 | |
| 265 | <ol> |
| 266 | <li><p id="offline">By Fossil itself when two users check in children to the same |
| 267 | leaf of a branch, as in Figure 2. |
| 268 | <br><br> |
| 269 | If the fork occurs because |
| 270 | autosync is disabled on one or both of the repositories or because |
| 271 | the user doing the check-in has no network connection at the moment |
| 272 | of the commit, Fossil has no way of knowing that it is creating a |
| 273 | fork until the two repositories are later synchronized.</p></li> |
| 274 | |
| @@ -250,11 +279,11 @@ | |
| 279 | negotiation; syncs don't automatically propagate up the clone tree |
| 280 | beyond that. Because of that, if you have a master repository and |
| 281 | Alice clones it, then Bobby clones from Alice's repository, a |
| 282 | check-in by Bobby that autosyncs with Alice's repo will <i>not</i> |
| 283 | also autosync with the master repo. The master doesn't get a copy of |
| 284 | Bobby's check-in until Alice <i>separately</i> syncs with the master. |
| 285 | If Carol cloned from the master repo and checks something in that |
| 286 | creates a fork relative to Bobby's check-in, the master repo won't |
| 287 | know about that fork until Alice syncs her repo with the master. |
| 288 | Even then, realize that Carol still won't know about the fork until |
| 289 | she subsequently syncs with the master repo. |
| @@ -262,40 +291,44 @@ | |
| 291 | One way to deal with this is to just accept it as a fact of using a |
| 292 | [https://en.wikipedia.org/wiki/Distributed_version_control|Distributed |
| 293 | Version Control System] like Fossil. |
| 294 | <br><br> |
| 295 | Another option, which we recommend you consider carefully, is to |
| 296 | make it a local policy that check-ins be made only directly against the master |
| 297 | repo or one of its immediate child clones so that the autosync |
| 298 | algorithm can do its job most effectively. Any clones deeper than |
| 299 | that should be treated as read-only and thus get a copy of the new |
| 300 | state of the world only once these central repos have negotiated |
| 301 | that new state. This policy avoids a class of inadvertent fork you |
| 302 | might not need to tolerate. Since [#bad-fork|forks on long-lived |
| 303 | shared working branches can end up dividing a team's development |
| 304 | effort], a team may easily justify this restriction on distributed |
| 305 | cloning.</p></li> |
| 306 | |
| 307 | <li><p id="automation">You've automated Fossil, so you use |
| 308 | <b>fossil commit --allow-fork</b> commands to prevent Fossil from |
| 309 | refusing the check-in simply because it would create a fork. |
| 310 | <br><br> |
| 311 | If you are writing such a tool — e.g. a shell script to make |
| 312 | multiple manipulations on a Fossil repo — it's better to make it |
| 313 | smart enough to detect this condition and cope with it, such as |
| 314 | by making a call to <b>[/help?cmd=update | fossil update]</b> |
| 315 | and checking for a merge conflict. That said, if the alternative is |
| 316 | losing information, you may feel justified in creating forks that an |
| 317 | interactive user must later manually clean up with <b>fossil merge</b> |
| 318 | commands.</p></li> |
| 319 | </ol> |
| 320 | |
| 321 | That leaves only one case where we can recommend use of "--allow-fork" |
| 322 | by interactive users: when you're working on a personal branch so that |
| 323 | creating a dual-tipped branch isn't going to cause any other user an |
| 324 | inconvenience or risk [#bad-fork | inadvertently forking the development |
| 325 | effort]. In such a case, the lone developer working on that branch is |
| 326 | not confused, since the fork in development is intentional. Sometimes it |
| 327 | simply makes no sense to bother creating a name, cluttering the global |
| 328 | branch namespace, simply to convert an intentional fork into a "branch." |
| 329 | This is especially the case when the fork is short-lived. |
| 330 | |
| 331 | There's a common generalization of that case: you're a solo developer, |
| 332 | so that the problems with branching vs forking simply don't matter. In |
| 333 | that case, feel free to use "--allow-fork" as much as you like. |
| 334 | |
| @@ -402,11 +435,11 @@ | |
| 435 | All users on this diagram start out with the same view of the |
| 436 | repository, cloned from the same master repo, and all of them are |
| 437 | working toward their shared vision of a unified future. |
| 438 | |
| 439 | All users, except possibly Alan, start out with the same two initial |
| 440 | check-ins in their local working clones, 1 & 2. It might be that Alan |
| 441 | starts out with only check-in 1 in his local clone, but we'll deal with |
| 442 | that detail later. |
| 443 | |
| 444 | It doesn't matter which branch this happy team is working on, only that |
| 445 | our example makes the most sense if you think of it as a long-lived shared |
| @@ -434,17 +467,17 @@ | |
| 467 | to that branch with a <b>fossil update $BRANCH</b> command. (There is an |
| 468 | implicit autosync in that command, if the option was enabled at the |
| 469 | time of the update.)</p></li> |
| 470 | |
| 471 | <li><p>The same thing, only in a fresh checkout directory with a |
| 472 | <b>[/help?cmd=open | fossil open $REPO $BRANCH]</b> command.</p></li> |
| 473 | |
| 474 | <li><p>Alan makes his check-in 3 while Betty has check-in 1 or 2 as |
| 475 | the tip in her local clone, but because she's working with an |
| 476 | autosync'd connection to the same upstream repository as Alan, on |
| 477 | attempting what will become check-in 4, she gets the "would fork" |
| 478 | message from <b>fossil commit</b>, so she dutifully updates her clone |
| 479 | and tries again, moving her work to be a child of the new tip, |
| 480 | check-in 3. (If she doesn't update, she creates a <i>second</i> |
| 481 | fork, which simply complicates matters beyond what we need here for |
| 482 | our illustration.)</p></li> |
| 483 | </ol> |
| @@ -575,26 +608,27 @@ | |
| 608 | <h3 id="unique">Branch Names Need Not Be Unique</h3> |
| 609 | |
| 610 | Fossil does not require that branch names be unique, as in some VCSes, |
| 611 | most notably Git. Just as with unnamed branches (which we call forks) |
| 612 | Fossil resolves such ambiguities using the timestamps on the latest |
| 613 | check-in in each branch. If you have two branches named "foo" and you say |
| 614 | <b>fossil update foo</b>, you get the tip of the "foo" branch with the most |
| 615 | recent check-in. |
| 616 | |
| 617 | This fact is helpful because it means you can reuse branch names, which |
| 618 | is especially useful with utility branches. There are several of these |
| 619 | in the SQLite and Fossil repositories: "broken-build," "declined," |
| 620 | "mistake," etc. As you might guess from these names, such branch names |
| 621 | are used in renaming the tip of one branch to shunt it off away from the |
| 622 | mainline of that branch due to some human error. (See |
| 623 | <b>[/help?cmd=amend | fossil |
| 624 | amend]</b> and the Fossil UI check-in amendment features.) This is a |
| 625 | workaround for Fossil's [./shunning.wiki|normal inability to forget |
| 626 | history]: we usually don't want to actually <i>remove</i> history, but |
| 627 | would like to sometimes set some of it aside under a new label. |
| 628 | |
| 629 | Because some VCSes can't cope with duplicate branch names, Fossil |
| 630 | collapses such names down on export using the same time stamp based |
| 631 | arbitration logic, so that only the branch with the newest check-in gets |
| 632 | the branch name in the export. |
| 633 | |
| 634 | All of the above is true of tags in general, not just branches. |
| 635 |