Fossil SCM
Updates to the fossil-v-git documentation to reduce the amount of Git-bashing and to try to make the document less confrontational.
Commit
358d7d8f0ee8e53c6f8c5b655725164ead12ad03e8b903f1b850c87460896a66
Parent
fc300d5a9aaeb54…
1 file changed
+78
-71
+78
-71
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -43,22 +43,22 @@ | ||
| 43 | 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | 46 | </tr> |
| 47 | 47 | <tr> |
| 48 | - <td>Sprawling collection of programs</td> | |
| 49 | - <td>Self-contained, stand-alone executable</td> | |
| 48 | + <td>A federation of many small programs</td> | |
| 49 | + <td>One self-contained, stand-alone executable</td> | |
| 50 | 50 | <td><a href="#selfcontained">2.2 ↓</a></td> |
| 51 | 51 | </tr> |
| 52 | 52 | <tr> |
| 53 | - <td>One-off custom pile-of-files data store</td> | |
| 54 | - <td>[https://sqlite.org/famous.html|The most popular database in the world]</td> | |
| 53 | + <td>Custom key/value data store</td> | |
| 54 | + <td>[https://sqlite.org/mostdeployed.html|The most used SQL database in the world]</td> | |
| 55 | 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | 56 | </tr> |
| 57 | 57 | <tr> |
| 58 | - <td>Runs natively on POSIX systems only</td> | |
| 59 | - <td>Native on common desktop & server platforms</td> | |
| 58 | + <td>Runs natively on POSIX systems</td> | |
| 59 | + <td>Runs natively on both POSIX and Windows</td> | |
| 60 | 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | 61 | </tr> |
| 62 | 62 | <tr> |
| 63 | 63 | <td>Bazaar-style development</td> |
| 64 | 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | ||
| 93 | 93 | <td>Commit first</td> |
| 94 | 94 | <td>Test first</td> |
| 95 | 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | 96 | </tr> |
| 97 | 97 | <tr> |
| 98 | - <td>SHA-2</td> | |
| 99 | - <td>SHA-3</td> | |
| 98 | + <td>SHA-1 or SHA-2</td> | |
| 99 | + <td>SHA-1 and/or SHA-3, in the same repository</td> | |
| 100 | 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | 101 | </tr> |
| 102 | 102 | </table></blockquote> |
| 103 | 103 | |
| 104 | 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | ||
| 117 | 117 | the design. One way to describe Fossil is that it is |
| 118 | 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | 119 | |
| 120 | 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | 121 | directories with a single command. For example, Fossil lets you say |
| 122 | -<tt>fossil all sync</tt> on a laptop prior to taking it off the network | |
| 122 | +"<tt>fossil all sync</tt>" on a laptop prior to taking it off the network | |
| 123 | 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | 126 | command gets you in sync. This works with several other Fossil |
| 127 | -sub-commands, such as <tt>fossil all changes</tt> to get a list of files | |
| 127 | +sub-commands, such as "<tt>fossil all changes</tt>" to get a list of files | |
| 128 | 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | 129 | all repos. |
| 130 | 130 | |
| 131 | 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -165,28 +165,30 @@ | ||
| 165 | 165 | manager, simply because the creation of complicated binary packages is |
| 166 | 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | 167 | not expected to build Git from source and install it themselves. |
| 168 | 168 | |
| 169 | 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | -depends only on common platform libraries. If your platform allows static | |
| 171 | -linking — not all do these days! — you can even get it down to | |
| 172 | -a single executable with no external dependencies at all. Most notably, | |
| 173 | -we deliver the official Windows builds of Fossil this way: the Zip file | |
| 174 | -contains only <tt>fossil.exe</tt>, a self-contained Fossil executable; | |
| 175 | -it is not a <tt>setup.exe</tt> style installer, it is the whole enchilada. | |
| 176 | - | |
| 177 | -A typical Fossil executable is about 5 MiB, not counting system | |
| 178 | -libraries it shares in common with Git such as OpenSSL and zlib, which | |
| 179 | -we can factor out of the discussion. | |
| 180 | - | |
| 181 | -These properties allow Fossil to easily run inside a minimally configured | |
| 182 | -[https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory | |
| 183 | -stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, | |
| 184 | -one merely puts the executable somewhere in the <tt>$PATH</tt>. Fossil is | |
| 185 | -[https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward | |
| 186 | -to build and install], so that many Fossil users do in fact build and | |
| 187 | -install "trunk" versions to get new features between formal releases. | |
| 170 | +depends only on common platform libraries. You can statically link | |
| 171 | +to get an executable with no external dependencies at all — a useful | |
| 172 | +feature for running inside of restrictive | |
| 173 | +[https://en.wikipedia.org/wiki/Chroot|chroot jail]. | |
| 174 | + | |
| 175 | +The precompiled Fossil binaries are delivered as just a single | |
| 176 | +executable. The precompiled Windows deliveries are just a ZIP archive | |
| 177 | +containing only "<tt>fossil.exe</tt>". There is no "<tt>setup.exe</tt>" | |
| 178 | +to run. Linux and Mac precompiled binaries are a tarball containing | |
| 179 | +just the "<tt>fossil</tt>" executable. To install, just put the | |
| 180 | +executable on your PATH. To uninstall, just delete the executable. | |
| 181 | +To upgrade (or downgrade) simply replace the executable. | |
| 182 | + | |
| 183 | +A typical Fossil executable is between 5 and 7 megabytes uncompressed | |
| 184 | +(as of 2020-12-12), | |
| 185 | +assuming that the executable is statically linked against OpenSSL. | |
| 186 | + | |
| 187 | +Fossil is easy to build from sources. Just run | |
| 188 | +"<tt>./configure && make</tt>" on POSIX systems and | |
| 189 | +"<tt>nmake /f Makefile.msc</tt>" on Windows. | |
| 188 | 190 | |
| 189 | 191 | Contrast a basic installation of Git, which takes up about |
| 190 | 192 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 191 | 193 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 192 | 194 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,87 +218,92 @@ | ||
| 216 | 218 | resource hungry] and hence more costly to run than the equivalent |
| 217 | 219 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 218 | 220 | a local rack server or blade to it, since its minimum requirements are |
| 219 | 221 | more or less a description of the smallest |
| 220 | 222 | thing you could call a "server" these days, but when you go to host that |
| 221 | -in the cloud, you can expect to pay about 8× as much to comfortably host | |
| 223 | +in the cloud, you can expect to pay about 8 times as much to comfortably host | |
| 222 | 224 | GitLab as for Fossil.³ This difference is largely due to basic |
| 223 | 225 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 224 | 226 | |
| 225 | 227 | The Fossil project itself is [./selfhost.wiki|hosted on a small and |
| 226 | 228 | inexpensive VPS]. A bare-bones $5/month VPS or a |
| 227 | 229 | spare Raspberry Pi is sufficient to run a full-up project |
| 228 | 230 | site, complete with tickets, wiki, and forum, in addition to |
| 229 | 231 | being a code repository. |
| 230 | 232 | |
| 231 | -<h3 id="durable" name="database">2.3 Durable</h3> | |
| 233 | +<h3 id="durable" name="database">2.3 Query Language</h3> | |
| 232 | 234 | |
| 233 | 235 | The baseline data structures for Fossil and Git are the same, modulo |
| 234 | 236 | formatting details. Both systems manage a |
| 235 | 237 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 236 | 238 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 237 | 239 | tree] structured check-in objects. |
| 238 | 240 | Check-ins are identified by a cryptographic hash of the check-in |
| 239 | -contents, and each check-in refers to its parent via <i>its</i> hash. | |
| 241 | +contents, and each check-in refers to its parent via the parent's hash. | |
| 240 | 242 | |
| 241 | 243 | The difference is that Git stores its objects as individual files in the |
| 242 | -<tt>.git</tt> folder or compressed into bespoke | |
| 244 | +<tt>.git</tt> folder or compressed into bespoke key/value | |
| 243 | 245 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 244 | 246 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 245 | -database file using a hybrid NoSQL/relational data model of the check-in | |
| 246 | -history. Git's data storage system is an ad-hoc pile-of-files key/value | |
| 247 | -database, whereas Fossil uses a proven, | |
| 248 | -[https://sqlite.org/testing.html|heavily-tested], general-purpose, | |
| 249 | -[https://sqlite.org/transactional.html|durable] SQL database. This | |
| 250 | -difference is more than an implementation detail. It has important | |
| 247 | +database file which provides ACID transactions and a high-level query | |
| 248 | +language. | |
| 249 | +This difference is more than an implementation detail. It has important | |
| 251 | 250 | practical consequences. |
| 252 | 251 | |
| 253 | -With Git, one can easily locate the ancestors of a particular check-in | |
| 252 | +One notable consequence is that it is difficult to find the descendents | |
| 253 | +of check-ins in Git. | |
| 254 | +One can easily locate the ancestors of a particular Git check-in | |
| 254 | 255 | by following the pointers embedded in the check-in object, but it is |
| 255 | 256 | difficult to go the other direction and locate the descendants of a |
| 256 | 257 | check-in. It is so difficult, in fact, that neither native Git nor |
| 257 | 258 | GitHub provide this capability short of crawling the |
| 258 | -[https://www.git-scm.com/docs/git-log|commit log]. With Git, if you | |
| 259 | -are looking at some historical check-in then you cannot ask "What came | |
| 260 | -next?" or "What are the children of this check-in?" | |
| 261 | - | |
| 262 | -Fossil, on the other hand, parses essential information about check-ins | |
| 263 | -(parents, children, committers, comments, files changed, etc.) into a | |
| 264 | -relational database that can easily be queried using concise SQL | |
| 265 | -statements to find both ancestors and descendants of a check-in. This is | |
| 266 | -the hybrid data model mentioned above: Fossil manages your check-in and | |
| 267 | -other data in a NoSQL [https://en.wikipedia.org/wiki/Merkle_tree | | |
| 268 | -Merkle tree] structured data store, but that's backed | |
| 269 | -by a set of relational lookup tables for quick indexing into that | |
| 270 | -artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The | |
| 271 | -Fossil DVCS]" for more details.) | |
| 259 | +[https://www.git-scm.com/docs/git-log|commit log]. With Fossil, | |
| 260 | +on the other hand, finding descendents is a simple SQL query. | |
| 261 | +It is common in Fossil to ask to see | |
| 262 | +[/timeline?d=release&n=all&y=ci&nd|all check-ins since the last release]. | |
| 263 | +Git lets you see "what came before". Fossil makes it just as | |
| 264 | +easy to also see "what came after". | |
| 272 | 265 | |
| 273 | 266 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 274 | 267 | difficult to locate and subject to garbage collection. This |
| 275 | 268 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 276 | -state] problem has caused untold grief for | |
| 277 | -[https://www.google.com/search?q=git+detached+head+state | a huge number | |
| 269 | +state] problem has caused grief for | |
| 270 | +[https://www.google.com/search?q=git+detached+head+state | many | |
| 278 | 271 | of Git users]. With |
| 279 | 272 | Fossil, detached heads are simply impossible because we can always find |
| 280 | -our way back into the Merkle tree using one or more of the relational | |
| 281 | -indices it automatically manages for you. | |
| 273 | +our way back into the Merkle tree using one or more of the relations | |
| 274 | +in the SQL database. | |
| 282 | 275 | |
| 283 | -This design difference shows up in several other places within each | |
| 284 | -tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more | |
| 285 | -detailed yet more clear than those available in Git front-ends. | |
| 286 | -(Contrast [/timeline?c=6df7a853ec16865b|this Fossil timeline] with | |
| 276 | +The SQL query capabilities of Fossil make it easier to track the | |
| 277 | +changes for one particular file within a project. For example, | |
| 278 | +you can easily find | |
| 279 | +[/finfo/www/fossil-v-git.wiki|the complete edit history of this one document], | |
| 280 | +or even | |
| 281 | +[/finfo/www/fossil-v-git.wiki?ubg|the same history color-coded by committer], | |
| 282 | +Both questions are simple SQL query in Fossil, with procedural code | |
| 283 | +only being used to format the result for display. | |
| 284 | +The same result could be obtained from Git, but because the data is | |
| 285 | +in a key/value store, much more procedural code has to be written to | |
| 286 | +walk the data and compute the result. And since that is a lot more | |
| 287 | +work, the question is seldom asked. | |
| 288 | + | |
| 289 | +The ease of querying Fossil data using SQL means that status or | |
| 290 | +history information about the project under management is easier | |
| 291 | +to obtain. And being easier means that it is more likely to happen. | |
| 292 | +Fossil reports tend to be more detailed and useful. | |
| 293 | +Consider the [/timeline?c=6df7a853ec16865b|this Fossil timeline] | |
| 294 | +compared to its | |
| 287 | 295 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 288 | -closest equivalent in GitHub].) It's why there is no inverse of the | |
| 289 | -cryptic <tt>@~</tt> notation in Git, meaning "the parent of HEAD," which | |
| 290 | -Fossil simply calls "prev", but there <i>is</i> a "next" | |
| 291 | -[./checkin_names.wiki|special check-in name] in Fossil. It is why Fossil | |
| 292 | -has so many [./webpage-ex.md|built-in status reports] to help maintain | |
| 293 | -situational awareness, aid comprehension, and avoid errors. | |
| 294 | - | |
| 295 | -These differences are due, in part, to Fossil's start a year later than | |
| 296 | -Git: we were able to learn from its key design mistakes. | |
| 297 | - | |
| 296 | +closest equivalent in GitHub]. Judge for yourself: Which of those | |
| 297 | +reports is more useful to a developer trying to understand what happened? | |
| 298 | + | |
| 299 | +The bottom line is that even though Fossil and Git are built around | |
| 300 | +the same low-level data structure, the use of SQL | |
| 301 | +to query this data makes the data more accessible in Fossil, resulting | |
| 302 | +in more detailed information being available to the user. This | |
| 303 | +improves situational awareness and makes working on the project | |
| 304 | +easier. | |
| 298 | 305 | |
| 299 | 306 | <h3 id="portable">2.4 Portable</h3> |
| 300 | 307 | |
| 301 | 308 | Fossil is largely written in ISO C, almost purely conforming to the |
| 302 | 309 | original 1989 standard. We make very little use of |
| 303 | 310 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -43,22 +43,22 @@ | |
| 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | </tr> |
| 47 | <tr> |
| 48 | <td>Sprawling collection of programs</td> |
| 49 | <td>Self-contained, stand-alone executable</td> |
| 50 | <td><a href="#selfcontained">2.2 ↓</a></td> |
| 51 | </tr> |
| 52 | <tr> |
| 53 | <td>One-off custom pile-of-files data store</td> |
| 54 | <td>[https://sqlite.org/famous.html|The most popular database in the world]</td> |
| 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | </tr> |
| 57 | <tr> |
| 58 | <td>Runs natively on POSIX systems only</td> |
| 59 | <td>Native on common desktop & server platforms</td> |
| 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | </tr> |
| 62 | <tr> |
| 63 | <td>Bazaar-style development</td> |
| 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | |
| 93 | <td>Commit first</td> |
| 94 | <td>Test first</td> |
| 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | </tr> |
| 97 | <tr> |
| 98 | <td>SHA-2</td> |
| 99 | <td>SHA-3</td> |
| 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | </tr> |
| 102 | </table></blockquote> |
| 103 | |
| 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | |
| 117 | the design. One way to describe Fossil is that it is |
| 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | |
| 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | directories with a single command. For example, Fossil lets you say |
| 122 | <tt>fossil all sync</tt> on a laptop prior to taking it off the network |
| 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | command gets you in sync. This works with several other Fossil |
| 127 | sub-commands, such as <tt>fossil all changes</tt> to get a list of files |
| 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | all repos. |
| 130 | |
| 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -165,28 +165,30 @@ | |
| 165 | manager, simply because the creation of complicated binary packages is |
| 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | not expected to build Git from source and install it themselves. |
| 168 | |
| 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | depends only on common platform libraries. If your platform allows static |
| 171 | linking — not all do these days! — you can even get it down to |
| 172 | a single executable with no external dependencies at all. Most notably, |
| 173 | we deliver the official Windows builds of Fossil this way: the Zip file |
| 174 | contains only <tt>fossil.exe</tt>, a self-contained Fossil executable; |
| 175 | it is not a <tt>setup.exe</tt> style installer, it is the whole enchilada. |
| 176 | |
| 177 | A typical Fossil executable is about 5 MiB, not counting system |
| 178 | libraries it shares in common with Git such as OpenSSL and zlib, which |
| 179 | we can factor out of the discussion. |
| 180 | |
| 181 | These properties allow Fossil to easily run inside a minimally configured |
| 182 | [https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory |
| 183 | stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, |
| 184 | one merely puts the executable somewhere in the <tt>$PATH</tt>. Fossil is |
| 185 | [https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward |
| 186 | to build and install], so that many Fossil users do in fact build and |
| 187 | install "trunk" versions to get new features between formal releases. |
| 188 | |
| 189 | Contrast a basic installation of Git, which takes up about |
| 190 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 191 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 192 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,87 +218,92 @@ | |
| 216 | resource hungry] and hence more costly to run than the equivalent |
| 217 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 218 | a local rack server or blade to it, since its minimum requirements are |
| 219 | more or less a description of the smallest |
| 220 | thing you could call a "server" these days, but when you go to host that |
| 221 | in the cloud, you can expect to pay about 8× as much to comfortably host |
| 222 | GitLab as for Fossil.³ This difference is largely due to basic |
| 223 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 224 | |
| 225 | The Fossil project itself is [./selfhost.wiki|hosted on a small and |
| 226 | inexpensive VPS]. A bare-bones $5/month VPS or a |
| 227 | spare Raspberry Pi is sufficient to run a full-up project |
| 228 | site, complete with tickets, wiki, and forum, in addition to |
| 229 | being a code repository. |
| 230 | |
| 231 | <h3 id="durable" name="database">2.3 Durable</h3> |
| 232 | |
| 233 | The baseline data structures for Fossil and Git are the same, modulo |
| 234 | formatting details. Both systems manage a |
| 235 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 236 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 237 | tree] structured check-in objects. |
| 238 | Check-ins are identified by a cryptographic hash of the check-in |
| 239 | contents, and each check-in refers to its parent via <i>its</i> hash. |
| 240 | |
| 241 | The difference is that Git stores its objects as individual files in the |
| 242 | <tt>.git</tt> folder or compressed into bespoke |
| 243 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 244 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 245 | database file using a hybrid NoSQL/relational data model of the check-in |
| 246 | history. Git's data storage system is an ad-hoc pile-of-files key/value |
| 247 | database, whereas Fossil uses a proven, |
| 248 | [https://sqlite.org/testing.html|heavily-tested], general-purpose, |
| 249 | [https://sqlite.org/transactional.html|durable] SQL database. This |
| 250 | difference is more than an implementation detail. It has important |
| 251 | practical consequences. |
| 252 | |
| 253 | With Git, one can easily locate the ancestors of a particular check-in |
| 254 | by following the pointers embedded in the check-in object, but it is |
| 255 | difficult to go the other direction and locate the descendants of a |
| 256 | check-in. It is so difficult, in fact, that neither native Git nor |
| 257 | GitHub provide this capability short of crawling the |
| 258 | [https://www.git-scm.com/docs/git-log|commit log]. With Git, if you |
| 259 | are looking at some historical check-in then you cannot ask "What came |
| 260 | next?" or "What are the children of this check-in?" |
| 261 | |
| 262 | Fossil, on the other hand, parses essential information about check-ins |
| 263 | (parents, children, committers, comments, files changed, etc.) into a |
| 264 | relational database that can easily be queried using concise SQL |
| 265 | statements to find both ancestors and descendants of a check-in. This is |
| 266 | the hybrid data model mentioned above: Fossil manages your check-in and |
| 267 | other data in a NoSQL [https://en.wikipedia.org/wiki/Merkle_tree | |
| 268 | Merkle tree] structured data store, but that's backed |
| 269 | by a set of relational lookup tables for quick indexing into that |
| 270 | artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The |
| 271 | Fossil DVCS]" for more details.) |
| 272 | |
| 273 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 274 | difficult to locate and subject to garbage collection. This |
| 275 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 276 | state] problem has caused untold grief for |
| 277 | [https://www.google.com/search?q=git+detached+head+state | a huge number |
| 278 | of Git users]. With |
| 279 | Fossil, detached heads are simply impossible because we can always find |
| 280 | our way back into the Merkle tree using one or more of the relational |
| 281 | indices it automatically manages for you. |
| 282 | |
| 283 | This design difference shows up in several other places within each |
| 284 | tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more |
| 285 | detailed yet more clear than those available in Git front-ends. |
| 286 | (Contrast [/timeline?c=6df7a853ec16865b|this Fossil timeline] with |
| 287 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 288 | closest equivalent in GitHub].) It's why there is no inverse of the |
| 289 | cryptic <tt>@~</tt> notation in Git, meaning "the parent of HEAD," which |
| 290 | Fossil simply calls "prev", but there <i>is</i> a "next" |
| 291 | [./checkin_names.wiki|special check-in name] in Fossil. It is why Fossil |
| 292 | has so many [./webpage-ex.md|built-in status reports] to help maintain |
| 293 | situational awareness, aid comprehension, and avoid errors. |
| 294 | |
| 295 | These differences are due, in part, to Fossil's start a year later than |
| 296 | Git: we were able to learn from its key design mistakes. |
| 297 | |
| 298 | |
| 299 | <h3 id="portable">2.4 Portable</h3> |
| 300 | |
| 301 | Fossil is largely written in ISO C, almost purely conforming to the |
| 302 | original 1989 standard. We make very little use of |
| 303 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -43,22 +43,22 @@ | |
| 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | </tr> |
| 47 | <tr> |
| 48 | <td>A federation of many small programs</td> |
| 49 | <td>One self-contained, stand-alone executable</td> |
| 50 | <td><a href="#selfcontained">2.2 ↓</a></td> |
| 51 | </tr> |
| 52 | <tr> |
| 53 | <td>Custom key/value data store</td> |
| 54 | <td>[https://sqlite.org/mostdeployed.html|The most used SQL database in the world]</td> |
| 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | </tr> |
| 57 | <tr> |
| 58 | <td>Runs natively on POSIX systems</td> |
| 59 | <td>Runs natively on both POSIX and Windows</td> |
| 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | </tr> |
| 62 | <tr> |
| 63 | <td>Bazaar-style development</td> |
| 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | |
| 93 | <td>Commit first</td> |
| 94 | <td>Test first</td> |
| 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | </tr> |
| 97 | <tr> |
| 98 | <td>SHA-1 or SHA-2</td> |
| 99 | <td>SHA-1 and/or SHA-3, in the same repository</td> |
| 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | </tr> |
| 102 | </table></blockquote> |
| 103 | |
| 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | |
| 117 | the design. One way to describe Fossil is that it is |
| 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | |
| 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | directories with a single command. For example, Fossil lets you say |
| 122 | "<tt>fossil all sync</tt>" on a laptop prior to taking it off the network |
| 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | command gets you in sync. This works with several other Fossil |
| 127 | sub-commands, such as "<tt>fossil all changes</tt>" to get a list of files |
| 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | all repos. |
| 130 | |
| 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -165,28 +165,30 @@ | |
| 165 | manager, simply because the creation of complicated binary packages is |
| 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | not expected to build Git from source and install it themselves. |
| 168 | |
| 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | depends only on common platform libraries. You can statically link |
| 171 | to get an executable with no external dependencies at all — a useful |
| 172 | feature for running inside of restrictive |
| 173 | [https://en.wikipedia.org/wiki/Chroot|chroot jail]. |
| 174 | |
| 175 | The precompiled Fossil binaries are delivered as just a single |
| 176 | executable. The precompiled Windows deliveries are just a ZIP archive |
| 177 | containing only "<tt>fossil.exe</tt>". There is no "<tt>setup.exe</tt>" |
| 178 | to run. Linux and Mac precompiled binaries are a tarball containing |
| 179 | just the "<tt>fossil</tt>" executable. To install, just put the |
| 180 | executable on your PATH. To uninstall, just delete the executable. |
| 181 | To upgrade (or downgrade) simply replace the executable. |
| 182 | |
| 183 | A typical Fossil executable is between 5 and 7 megabytes uncompressed |
| 184 | (as of 2020-12-12), |
| 185 | assuming that the executable is statically linked against OpenSSL. |
| 186 | |
| 187 | Fossil is easy to build from sources. Just run |
| 188 | "<tt>./configure && make</tt>" on POSIX systems and |
| 189 | "<tt>nmake /f Makefile.msc</tt>" on Windows. |
| 190 | |
| 191 | Contrast a basic installation of Git, which takes up about |
| 192 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 193 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 194 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,87 +218,92 @@ | |
| 218 | resource hungry] and hence more costly to run than the equivalent |
| 219 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 220 | a local rack server or blade to it, since its minimum requirements are |
| 221 | more or less a description of the smallest |
| 222 | thing you could call a "server" these days, but when you go to host that |
| 223 | in the cloud, you can expect to pay about 8 times as much to comfortably host |
| 224 | GitLab as for Fossil.³ This difference is largely due to basic |
| 225 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 226 | |
| 227 | The Fossil project itself is [./selfhost.wiki|hosted on a small and |
| 228 | inexpensive VPS]. A bare-bones $5/month VPS or a |
| 229 | spare Raspberry Pi is sufficient to run a full-up project |
| 230 | site, complete with tickets, wiki, and forum, in addition to |
| 231 | being a code repository. |
| 232 | |
| 233 | <h3 id="durable" name="database">2.3 Query Language</h3> |
| 234 | |
| 235 | The baseline data structures for Fossil and Git are the same, modulo |
| 236 | formatting details. Both systems manage a |
| 237 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 238 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 239 | tree] structured check-in objects. |
| 240 | Check-ins are identified by a cryptographic hash of the check-in |
| 241 | contents, and each check-in refers to its parent via the parent's hash. |
| 242 | |
| 243 | The difference is that Git stores its objects as individual files in the |
| 244 | <tt>.git</tt> folder or compressed into bespoke key/value |
| 245 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 246 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 247 | database file which provides ACID transactions and a high-level query |
| 248 | language. |
| 249 | This difference is more than an implementation detail. It has important |
| 250 | practical consequences. |
| 251 | |
| 252 | One notable consequence is that it is difficult to find the descendents |
| 253 | of check-ins in Git. |
| 254 | One can easily locate the ancestors of a particular Git check-in |
| 255 | by following the pointers embedded in the check-in object, but it is |
| 256 | difficult to go the other direction and locate the descendants of a |
| 257 | check-in. It is so difficult, in fact, that neither native Git nor |
| 258 | GitHub provide this capability short of crawling the |
| 259 | [https://www.git-scm.com/docs/git-log|commit log]. With Fossil, |
| 260 | on the other hand, finding descendents is a simple SQL query. |
| 261 | It is common in Fossil to ask to see |
| 262 | [/timeline?d=release&n=all&y=ci&nd|all check-ins since the last release]. |
| 263 | Git lets you see "what came before". Fossil makes it just as |
| 264 | easy to also see "what came after". |
| 265 | |
| 266 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 267 | difficult to locate and subject to garbage collection. This |
| 268 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 269 | state] problem has caused grief for |
| 270 | [https://www.google.com/search?q=git+detached+head+state | many |
| 271 | of Git users]. With |
| 272 | Fossil, detached heads are simply impossible because we can always find |
| 273 | our way back into the Merkle tree using one or more of the relations |
| 274 | in the SQL database. |
| 275 | |
| 276 | The SQL query capabilities of Fossil make it easier to track the |
| 277 | changes for one particular file within a project. For example, |
| 278 | you can easily find |
| 279 | [/finfo/www/fossil-v-git.wiki|the complete edit history of this one document], |
| 280 | or even |
| 281 | [/finfo/www/fossil-v-git.wiki?ubg|the same history color-coded by committer], |
| 282 | Both questions are simple SQL query in Fossil, with procedural code |
| 283 | only being used to format the result for display. |
| 284 | The same result could be obtained from Git, but because the data is |
| 285 | in a key/value store, much more procedural code has to be written to |
| 286 | walk the data and compute the result. And since that is a lot more |
| 287 | work, the question is seldom asked. |
| 288 | |
| 289 | The ease of querying Fossil data using SQL means that status or |
| 290 | history information about the project under management is easier |
| 291 | to obtain. And being easier means that it is more likely to happen. |
| 292 | Fossil reports tend to be more detailed and useful. |
| 293 | Consider the [/timeline?c=6df7a853ec16865b|this Fossil timeline] |
| 294 | compared to its |
| 295 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 296 | closest equivalent in GitHub]. Judge for yourself: Which of those |
| 297 | reports is more useful to a developer trying to understand what happened? |
| 298 | |
| 299 | The bottom line is that even though Fossil and Git are built around |
| 300 | the same low-level data structure, the use of SQL |
| 301 | to query this data makes the data more accessible in Fossil, resulting |
| 302 | in more detailed information being available to the user. This |
| 303 | improves situational awareness and makes working on the project |
| 304 | easier. |
| 305 | |
| 306 | <h3 id="portable">2.4 Portable</h3> |
| 307 | |
| 308 | Fossil is largely written in ISO C, almost purely conforming to the |
| 309 | original 1989 standard. We make very little use of |
| 310 |