|
1
|
<title>Fossil Versus Git</title> |
|
2
|
|
|
3
|
<h2>1.0 Don't Stress!</h2> |
|
4
|
|
|
5
|
The feature sets of Fossil and [http://git-scm.com | Git] overlap in |
|
6
|
many ways. Both are |
|
7
|
[https://en.wikipedia.org/wiki/Distributed_version_control | distributed |
|
8
|
version control systems] which store a tree of check-in objects to a |
|
9
|
local repository clone. In both systems, the local clone starts out as a |
|
10
|
full copy of the remote parent. New content gets added to the local |
|
11
|
clone and then later optionally pushed up to the remote, and changes to |
|
12
|
the remote can be pulled down to the local clone at will. Both systems |
|
13
|
offer diffing, patching, branching, merging, cherry-picking, bisecting, |
|
14
|
private branches, a stash, etc. |
|
15
|
|
|
16
|
Fossil has inbound and outbound Git conversion features, so if you start |
|
17
|
out using one DVCS and later decide you like the other better, you can |
|
18
|
easily [./inout.wiki | move your version-controlled file content].¹ |
|
19
|
|
|
20
|
In this document, we set all of that similarity and interoperability |
|
21
|
aside and focus on the important differences between the two, especially |
|
22
|
those that impact the user experience. |
|
23
|
|
|
24
|
Keep in mind that you are reading this on a Fossil website, and though |
|
25
|
we try to be fair, the information here |
|
26
|
might be biased in favor of Fossil, if only because we spend most of our |
|
27
|
time using Fossil, not Git. Ask around for second opinions from |
|
28
|
people who have used <em>both</em> Fossil and Git. |
|
29
|
|
|
30
|
If you want a more practical, less philosophical guide to moving from |
|
31
|
Git to Fossil, see our [./gitusers.md | Git to Fossil Translation Guide]. |
|
32
|
|
|
33
|
|
|
34
|
<h2>2.0 Differences Between Fossil And Git</h2> |
|
35
|
|
|
36
|
Differences between Fossil and Git are summarized by the following table, |
|
37
|
with further description in the text that follows. |
|
38
|
|
|
39
|
<table style="width: fit-content"> |
|
40
|
<tr><th>GIT</th><th>FOSSIL</th><th>more</th></tr> |
|
41
|
<tr> |
|
42
|
<td>File versioning only</td> |
|
43
|
<td> |
|
44
|
VCS, tickets, wiki, docs, notes, forum, chat, UI, |
|
45
|
[https://en.wikipedia.org/wiki/Role-based_access_control|RBAC] |
|
46
|
</td> |
|
47
|
<td><a href="#features">2.1 ↓</a></td> |
|
48
|
</tr> |
|
49
|
<tr> |
|
50
|
<td>A federation of many small programs</td> |
|
51
|
<td>One self-contained, stand-alone executable</td> |
|
52
|
<td><a href="#selfcontained">2.2 ↓</a></td> |
|
53
|
</tr> |
|
54
|
<tr> |
|
55
|
<td>Custom key/value data store</td> |
|
56
|
<td>[https://sqlite.org/mostdeployed.html|The most used SQL database in the world]</td> |
|
57
|
<td><a href="#durable">2.3 ↓</a></td> |
|
58
|
</tr> |
|
59
|
<tr> |
|
60
|
<td>Runs natively on POSIX systems</td> |
|
61
|
<td>Runs natively on both POSIX and Windows</td> |
|
62
|
<td><a href="#portable">2.4 ↓</a></td> |
|
63
|
</tr> |
|
64
|
<tr> |
|
65
|
<td>Bazaar-style development</td> |
|
66
|
<td>Cathedral-style development</td> |
|
67
|
<td><a href="#devorg">2.5.1 ↓</a></td> |
|
68
|
</tr> |
|
69
|
<tr> |
|
70
|
<td>Designed for Linux kernel development</td> |
|
71
|
<td>Designed for SQLite development</td> |
|
72
|
<td><a href="#scale">2.5.2 ↓</a></td> |
|
73
|
</tr> |
|
74
|
<tr> |
|
75
|
<td>Focus on individual branches</td> |
|
76
|
<td>Focus on the entire tree of changes</td> |
|
77
|
<td><a href="#branches">2.5.3 ↓</a></td> |
|
78
|
</tr> |
|
79
|
<tr> |
|
80
|
<td>One check-out per repository</td> |
|
81
|
<td>Many check-outs per repository</td> |
|
82
|
<td><a href="#checkouts">2.6 ↓</a></td> |
|
83
|
</tr> |
|
84
|
<tr> |
|
85
|
<td>Remembers what you should have done</td> |
|
86
|
<td>Remembers what you actually did</td> |
|
87
|
<td><a href="#history">2.7 ↓</a></td> |
|
88
|
</tr> |
|
89
|
<tr> |
|
90
|
<td>Commit first</td> |
|
91
|
<td>Test first</td> |
|
92
|
<td><a href="#testing">2.8 ↓</a></td> |
|
93
|
</tr> |
|
94
|
<tr> |
|
95
|
<td>SHA-1 or SHA-2</td> |
|
96
|
<td>SHA-1 and/or SHA-3, in the same repository</td> |
|
97
|
<td><a href="#hash">2.9 ↓</a></td> |
|
98
|
</tr> |
|
99
|
</table> |
|
100
|
|
|
101
|
<h3 id="features">2.1 Featureful</h3> |
|
102
|
|
|
103
|
Git provides file versioning services only, whereas Fossil adds |
|
104
|
an integrated [./wikitheory.wiki | wiki], |
|
105
|
[./bugtheory.wiki | ticketing & bug tracking], |
|
106
|
[./embeddeddoc.wiki | embedded documentation], |
|
107
|
[./event.wiki | technical notes], a [./forum.wiki | web forum], |
|
108
|
and a [./chat.md | chat service], |
|
109
|
all within a single nicely-designed [./customskin.md|skinnable] web |
|
110
|
[/help/ui|UI], |
|
111
|
protected by [./caps/ | a fine-grained role-based |
|
112
|
access control system]. |
|
113
|
These additional capabilities are available for Git as 3rd-party |
|
114
|
add-ons, but with Fossil they are integrated into |
|
115
|
the design, to the point that it approximates |
|
116
|
"[https://github.com/ | GitHub]-in-a-box." |
|
117
|
|
|
118
|
Even if you only want straight version control, Fossil has affordances |
|
119
|
not available in Git. |
|
120
|
|
|
121
|
For instance, Fossil can do operations over all local repo clones and |
|
122
|
check-out directories with a single command. You can say "<tt>fossil |
|
123
|
all sync</tt>" on a laptop prior to taking it off the network hosting |
|
124
|
those repos, as before going on a trip. It doesn't matter if those |
|
125
|
repos are private and restricted to your company network or public |
|
126
|
Internet-hosted repos, you get synced up with everything you need while |
|
127
|
off-network. |
|
128
|
|
|
129
|
You get the same capability with several other Fossil |
|
130
|
sub-commands as well, such as "<tt>fossil all changes</tt>" to get a list of files |
|
131
|
that you forgot to commit prior to the end of your working day, across |
|
132
|
all repos. |
|
133
|
|
|
134
|
Whenever Fossil is told to modify the local checkout in some destructive |
|
135
|
way ([/help/rm|fossil rm], [/help/update|fossil update], |
|
136
|
[/help/revert|fossil revert], etc.) Fossil remembers the prior state |
|
137
|
and is able to return the check-out directory to that state with a |
|
138
|
<tt>fossil undo</tt> command. While you cannot undo a commit in Fossil |
|
139
|
— [#history | on purpose!] — as long as the change remains confined to |
|
140
|
the local check-out directory only, Fossil makes undo |
|
141
|
[https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things|easier than in |
|
142
|
Git]. |
|
143
|
|
|
144
|
For developers who choose to self-host projects rather than rely on a |
|
145
|
3rd-party service such as GitHub, Fossil is much easier to set up: |
|
146
|
the stand-alone Fossil executable together with a [./server/any/cgi.md|2-line CGI script] |
|
147
|
suffice to instantiate a full-featured developer website. To accomplish |
|
148
|
the same using Git requires locating, installing, configuring, integrating, |
|
149
|
and managing a wide assortment of separate tools. Standing up a developer |
|
150
|
website using Fossil can be done in minutes, whereas doing the same using |
|
151
|
Git requires hours or days. |
|
152
|
|
|
153
|
Fossil is small, complete, and self-contained. If you clone |
|
154
|
[https://github.com/git/git|Git's self-hosting repository], you get just |
|
155
|
Git's source code. If you clone Fossil's self-hosting repository, you |
|
156
|
get the entire Fossil website — source code, documentation, ticket |
|
157
|
history, and so forth.² That means you get a copy of this very article |
|
158
|
and all of its historical versions, plus the same for all of the other |
|
159
|
public content on this site. |
|
160
|
|
|
161
|
|
|
162
|
<h3 id="selfcontained" name="selfcontained">2.2 Self Contained</h3> |
|
163
|
|
|
164
|
Git is actually a collection of many small tools, each doing one small |
|
165
|
part of the job, which can be recombined (by experts) to perform |
|
166
|
powerful operations. Git has a lot of complexity and many dependencies, |
|
167
|
so that most people end up installing it via some kind of package |
|
168
|
manager, simply because the creation of complicated binary packages is |
|
169
|
best delegated to people skilled in their creation. Normal Git users are |
|
170
|
not expected to build Git from source and install it themselves. |
|
171
|
|
|
172
|
Fossil is a single self-contained stand-alone executable which |
|
173
|
depends only on common platform libraries in its default configuration. |
|
174
|
To install one of [https://fossil-scm.org/home/uv/download.html | our |
|
175
|
precompiled binaries], unpack the executable from the archive and put it |
|
176
|
somewhere in your <tt>PATH</tt>. To uninstall it, delete the executable. |
|
177
|
|
|
178
|
This policy is particularly useful when running Fossil inside a |
|
179
|
restrictive container, anything from [./chroot.md | classic chroot |
|
180
|
jails] to modern [https://en.wikipedia.org/wiki/OS-level_virtualization |
|
181
|
| OS-level virtualization mechanisms] such as |
|
182
|
[https://en.wikipedia.org/wiki/Docker_(software) | Docker]. |
|
183
|
Our [./containers.md | stock container image] is under 8 MB when |
|
184
|
uncompressed and running. It contains nothing but a single |
|
185
|
statically-linked binary. |
|
186
|
|
|
187
|
If you build a dynamically linked binary instead, Fossil's on-disk size |
|
188
|
drops to around 6 MB, and it's dependent only on widespread |
|
189
|
platform libraries with stable ABIs such as glibc, zlib, and openssl. |
|
190
|
|
|
191
|
Full static linking is easier on Windows, so our precompiled Windows |
|
192
|
binaries are just a ZIP archive |
|
193
|
containing only "<tt>fossil.exe</tt>". There is no "<tt>setup.exe</tt>" |
|
194
|
to run. |
|
195
|
|
|
196
|
Fossil is easy to build from sources. Just run |
|
197
|
"<tt>./configure && make</tt>" on POSIX systems and |
|
198
|
"<tt>nmake /f Makefile.msc</tt>" on Windows. |
|
199
|
|
|
200
|
Contrast a basic installation of Git, which takes up about |
|
201
|
15 MiB on Debian 10 across 230 files, not counting the contents of |
|
202
|
<tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
|
203
|
deploy to any platform where you cannot count on facilities like the POSIX |
|
204
|
shell, Perl interpreter, and Tcl/Tk platform needed to fully use Git |
|
205
|
as part of the base platform, the full footprint of a Git installation |
|
206
|
extends to more like 45 MiB and thousands of files. This complicates |
|
207
|
several common scenarios: Git for Windows, chrooted Git servers, |
|
208
|
Docker images... |
|
209
|
|
|
210
|
Some say that Git more closely adheres to the Unix philosophy, |
|
211
|
summarized as "many small tools, loosely joined," but we have many |
|
212
|
examples of other successful Unix software that violates that principle |
|
213
|
to good effect, from Apache to Python to ZFS. We can infer from that |
|
214
|
that this is not an absolute principle of good software design. |
|
215
|
Sometimes "many features, tightly-coupled" works better. What actually |
|
216
|
matters is effectiveness and efficiency. We believe Fossil achieves |
|
217
|
this. |
|
218
|
|
|
219
|
The above size comparisons aren't apples-to-apples anyway. We've |
|
220
|
compared the size of Fossil with all of its [#features | many built-in |
|
221
|
features] to a fairly minimal Git installation. You must add a lot of |
|
222
|
third-party software to Git to give it a Fossil-equivalent feature set. |
|
223
|
Consider [https://about.gitlab.com/|GitLab], a third-party extension to |
|
224
|
Git wrapping it in many features, making it roughly Fossil-equivalent, |
|
225
|
though [https://docs.gitlab.com/ee/install/requirements.html|much more |
|
226
|
resource hungry] and hence more costly to run than the equivalent Fossil |
|
227
|
setup. [https://hub.docker.com/r/gitlab/gitlab-ce/ | The official GitLab |
|
228
|
Community Edition container] currently clocks in at 2.66 GiB! |
|
229
|
|
|
230
|
GitLab's requirements are easy to accept when you're dedicating |
|
231
|
a local rack server or blade to it, since its minimum requirements are |
|
232
|
more or less a description of the smallest |
|
233
|
thing you could call a "server" these days, but when you go to host that |
|
234
|
in the cloud, you can expect to pay about 8 times as much to comfortably host |
|
235
|
GitLab as for Fossil.³ This difference is largely due to basic |
|
236
|
technology choices: Ruby and PostgreSQL vs C and SQLite. |
|
237
|
|
|
238
|
The Fossil project itself is [./selfhost.wiki|hosted on a small and |
|
239
|
inexpensive VPS]. A bare-bones $5/month VPS or a |
|
240
|
spare Raspberry Pi is sufficient to run a full-up project |
|
241
|
site, complete with tickets, wiki, chat, and forum, in addition to |
|
242
|
being a code repository. |
|
243
|
|
|
244
|
<h3 id="durable" name="database">2.3 Query Language</h3> |
|
245
|
|
|
246
|
The baseline data structures for Fossil and Git are the same, modulo |
|
247
|
formatting details. Both systems manage a |
|
248
|
[https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
|
249
|
graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
|
250
|
tree] structured check-in objects. |
|
251
|
Check-ins are identified by a cryptographic hash of the check-in |
|
252
|
contents, and each check-in refers to its parent via the parent's hash. |
|
253
|
|
|
254
|
The difference is that Git stores its objects as individual files in the |
|
255
|
<tt>.git</tt> folder or compressed into bespoke key/value |
|
256
|
[https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
|
257
|
whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
|
258
|
database file which provides ACID transactions and a high-level query |
|
259
|
language. |
|
260
|
This difference is more than an implementation detail. It has important |
|
261
|
practical consequences. |
|
262
|
|
|
263
|
One notable consequence is that it is difficult to find the descendants |
|
264
|
of check-ins in Git. |
|
265
|
One can easily locate the ancestors of a particular Git check-in |
|
266
|
by following the pointers embedded in the check-in object, but it is |
|
267
|
difficult to go the other direction and locate the descendants of a |
|
268
|
check-in. It is so difficult, in fact, that neither native Git nor |
|
269
|
GitHub provide this capability short of crawling the |
|
270
|
[https://www.git-scm.com/docs/git-log|commit log]. With Fossil, |
|
271
|
on the other hand, finding descendants is a simple SQL query. |
|
272
|
It is common in Fossil to ask to see |
|
273
|
[/timeline?df=release&y=ci|all check-ins since the last release]. |
|
274
|
Git lets you see "what came before". Fossil makes it just as |
|
275
|
easy to also see "what came after". |
|
276
|
|
|
277
|
Leaf check-ins in Git that lack a "ref" become "detached," making them |
|
278
|
difficult to locate and subject to garbage collection. This |
|
279
|
[https://stackoverflow.com/q/3965676 | detached head |
|
280
|
state] problem has caused grief for |
|
281
|
[https://www.google.com/search?q=git+detached+head+state | many |
|
282
|
Git users]. With |
|
283
|
Fossil, detached heads are simply impossible because we can always find |
|
284
|
our way back into the Merkle tree using one or more of the relations |
|
285
|
in the SQL database. |
|
286
|
|
|
287
|
The SQL query capabilities of Fossil make it easier to track the |
|
288
|
changes for one particular file within a project. For example, |
|
289
|
you can easily find |
|
290
|
[/finfo/www/fossil-v-git.wiki|the complete edit history of this one document], |
|
291
|
or even |
|
292
|
[/finfo/www/fossil-v-git.wiki?ubg|the same history color-coded by committer], |
|
293
|
Both questions are simple SQL query in Fossil, with procedural code |
|
294
|
only being used to format the result for display. |
|
295
|
The same result could be obtained from Git, but because the data is |
|
296
|
in a key/value store, much more procedural code has to be written to |
|
297
|
walk the data and compute the result. And since that is a lot more |
|
298
|
work, the question is seldom asked. |
|
299
|
|
|
300
|
The ease of querying Fossil data using SQL means that status or |
|
301
|
history information about the project under management is easier |
|
302
|
to obtain. Being easier means that it is more likely to happen. |
|
303
|
Fossil reports tend to be more detailed and useful. |
|
304
|
Compare [/timeline?c=6df7a853ec16865b|this Fossil timeline] |
|
305
|
to |
|
306
|
[https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34 | |
|
307
|
its closest equivalent in GitHub]. Judge for yourself: which of those |
|
308
|
reports is more useful to a developer trying to understand what happened? |
|
309
|
|
|
310
|
The bottom line is that even though Fossil and Git are built around |
|
311
|
the same low-level data structure, the use of SQL |
|
312
|
to query this data makes the data more accessible in Fossil, resulting |
|
313
|
in more detailed information being available to the user. This |
|
314
|
improves situational awareness and makes working on the project |
|
315
|
easier. |
|
316
|
|
|
317
|
<h3 id="portable">2.4 Portable</h3> |
|
318
|
|
|
319
|
Fossil is largely written in ISO C, almost purely conforming to the |
|
320
|
original 1989 standard. We make very little use of |
|
321
|
[https://en.wikipedia.org/wiki/C99|C99], and we do not knowingly make |
|
322
|
any use of |
|
323
|
[https://en.wikipedia.org/wiki/C11_(C_standard_revision)|C11]. Fossil |
|
324
|
does call POSIX and Windows APIs where necessary, but it's about |
|
325
|
as portable as you can ask given that ISO C doesn't define all of the |
|
326
|
facilities Fossil needs to do its thing. (Network sockets, file locking, |
|
327
|
etc.) There are certainly well-known platforms Fossil hasn't been ported |
|
328
|
to yet, but that's most likely due to lack of interest rather than |
|
329
|
inherent difficulties in doing the port. We believe the most stringent |
|
330
|
limit on its portability is that it assumes at least a 32-bit CPU and |
|
331
|
several megs of flat-addressed memory.⁴ Fossil isn't quite as |
|
332
|
[https://www.sqlite.org/custombuild.html|portable as SQLite], but it's |
|
333
|
close. |
|
334
|
|
|
335
|
Over half of the C code in Fossil is actually an embedded copy of the |
|
336
|
current version of SQLite. Much of what is Fossil-specific after you set |
|
337
|
SQLite itself aside is SQL code calling into SQLite. The number of lines |
|
338
|
of SQL code in Fossil isn't large by percentage, but since SQL is such |
|
339
|
an expressive, declarative language, it has an outsized contribution to |
|
340
|
Fossil's user-visible functionality. |
|
341
|
|
|
342
|
Fossil isn't entirely C and SQL code. Its web UI [./javascript.md | |
|
343
|
uses JavaScript where |
|
344
|
necessary]. The server-side |
|
345
|
UI scripting uses a custom minimal |
|
346
|
[https://en.wikipedia.org/wiki/Tcl|Tcl] dialect called |
|
347
|
[./th1.md|TH1], which is |
|
348
|
embedded into Fossil itself. Fossil's build system and test suite are |
|
349
|
largely based on Tcl.⁵ All of this is quite portable. |
|
350
|
|
|
351
|
About half of Git's code is POSIX C, and about a third is POSIX shell |
|
352
|
code. This is largely why the so-called "Git for Windows" distributions |
|
353
|
(both [https://git-scm.com/download/win|first-party] and |
|
354
|
[https://gitforwindows.org/|third-party]) are actually an |
|
355
|
[https://www.msys2.org/wiki/Home/|MSYS POSIX portability environment] bundled |
|
356
|
with all of the Git stuff, because it would be too painful to port Git |
|
357
|
natively to Windows. Git is a foreign citizen on Windows, speaking to it |
|
358
|
only through a translator.⁶ |
|
359
|
|
|
360
|
While Fossil does lean toward POSIX norms when given a choice — LF-only |
|
361
|
line endings are treated as first-class citizens over CR+LF, for example |
|
362
|
— the Windows build of Fossil is truly native. |
|
363
|
|
|
364
|
The third-party extensions to Git tend to follow this same pattern. |
|
365
|
[https://docs.gitlab.com/ee/install/install_methods.html#microsoft-windows | |
|
366
|
GitLab isn't portable to Windows at all], |
|
367
|
for example. For that matter, GitLab isn't even officially supported on |
|
368
|
macOS, the BSDs, or uncommon Linuxes! We have many users who regularly |
|
369
|
build and run Fossil on all of these systems. |
|
370
|
|
|
371
|
|
|
372
|
<h3 id="vs-linux">2.5 Linux vs. SQLite</h3> |
|
373
|
|
|
374
|
Fossil and Git promote different development styles because each one was |
|
375
|
specifically designed to support the creator's main software |
|
376
|
development project: [https://en.wikipedia.org/wiki/Linus_Torvalds|Linus |
|
377
|
Torvalds] designed Git to support development of |
|
378
|
[https://www.kernel.org/|the Linux kernel], and |
|
379
|
[https://en.wikipedia.org/wiki/D._Richard_Hipp|D. Richard Hipp] designed |
|
380
|
Fossil to support the development of [https://sqlite.org/|SQLite]. |
|
381
|
Both projects must rank high on any objective list of "most |
|
382
|
important FOSS projects," yet these two projects are almost entirely unlike |
|
383
|
one another, so it is natural that the DVCSes created to support these |
|
384
|
projects also differ in many ways. |
|
385
|
|
|
386
|
In the following sections, we will explain how four key differences |
|
387
|
between the Linux and SQLite software development projects dictated the |
|
388
|
design of each DVCS's low-friction usage path. |
|
389
|
|
|
390
|
When deciding between these two DVCSes, you should ask yourself, "Is my |
|
391
|
project more like Linux or more like SQLite?" |
|
392
|
|
|
393
|
|
|
394
|
<h4 id="devorg">2.5.1 Development Organization</h4> |
|
395
|
|
|
396
|
Eric S. Raymond's seminal essay-turned-book |
|
397
|
"[https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar|The |
|
398
|
Cathedral and the Bazaar]" details the two major development |
|
399
|
organization styles found in |
|
400
|
[https://en.wikipedia.org/wiki/Free_and_open-source_software|FOSS] |
|
401
|
projects. As it happens, Linux and SQLite fall on opposite sides of this |
|
402
|
dichotomy. Differing development organization styles dictate a different |
|
403
|
design and low-friction usage path in the tools created to support each |
|
404
|
project. |
|
405
|
|
|
406
|
Git promotes the Linux kernel's bazaar development style, in which a |
|
407
|
loosely-associated mass of developers contribute their work through |
|
408
|
[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|a |
|
409
|
hierarchy of lieutenants] who manage and clean up these contributions |
|
410
|
for consideration by Linus Torvalds, who has the power to cherry-pick |
|
411
|
individual contributions into his version of the Linux kernel. Git |
|
412
|
allows an anonymous developer to rebase and push specific locally-named |
|
413
|
private branches, so that a Git repo clone often isn't really a clone at |
|
414
|
all: it may have an arbitrary number of differences relative to the |
|
415
|
repository it originally cloned from. Git encourages siloed development. |
|
416
|
Select work in a developer's local repository may remain private |
|
417
|
indefinitely. |
|
418
|
|
|
419
|
All of this is exactly what one wants when doing bazaar-style |
|
420
|
development. |
|
421
|
|
|
422
|
Fossil's normal mode of operation differs on every one of these points, |
|
423
|
with the specific designed-in goal of promoting SQLite's cathedral |
|
424
|
development model: |
|
425
|
|
|
426
|
* <b>Personal engagement:</b> SQLite's developers know each |
|
427
|
other by name and work together daily on the project. |
|
428
|
|
|
429
|
* <b>Trust over hierarchy:</b> SQLite's developers check |
|
430
|
changes into their local repository, and these are immediately and |
|
431
|
automatically synchronized up to the central repository; there is no |
|
432
|
"[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|dictator |
|
433
|
and lieutenants]" hierarchy as with Linux kernel contributions. D. |
|
434
|
Richard Hipp rarely overrides decisions made by those he has trusted |
|
435
|
with commit access on his repositories. Fossil allows you to give |
|
436
|
[./caps/admin-v-setup.md|some users] more power over what |
|
437
|
they can do with the repository, but Fossil [./caps/index.md#ucap | |
|
438
|
only loosely supports] the enforcement of a development organization's |
|
439
|
social and power hierarchies. Fossil is a great fit for |
|
440
|
[https://en.wikipedia.org/wiki/Flat_organization|flat |
|
441
|
organizations]. |
|
442
|
|
|
443
|
* <b>No easy drive-by contributions:</b> Git |
|
444
|
[https://www.git-scm.com/docs/git-request-pull|pull requests] offer |
|
445
|
a low-friction path to accepting |
|
446
|
[https://www.jonobacon.com/2012/07/25/building-strong-community-structural-integrity/|drive-by |
|
447
|
contributions]. Fossil's closest equivalents are its unique |
|
448
|
[/help/bundle|bundle] and [/help/patch|patch] features, which require higher engagement |
|
449
|
than firing off a PR.⁷ This difference comes directly from the |
|
450
|
initial designed purpose for each tool: the SQLite project doesn't |
|
451
|
accept outside contributions from previously-unknown developers, but |
|
452
|
the Linux kernel does. |
|
453
|
|
|
454
|
* <b>No rebasing:</b> When your local repo clone syncs changes |
|
455
|
up to its parent, those changes are sent exactly as they were |
|
456
|
committed locally. [#history|There is no rebasing mechanism in |
|
457
|
Fossil, on purpose.] |
|
458
|
|
|
459
|
* <b>Sync over push:</b> Explicit pushes are uncommon in |
|
460
|
Fossil-based projects: the default is to rely on |
|
461
|
[/help/autosync|autosync mode] instead, in which each commit |
|
462
|
syncs immediately to its parent repository. This is a mode so you |
|
463
|
can turn it off temporarily when needed, such as when working |
|
464
|
offline. Fossil is still a truly distributed version control system; |
|
465
|
it's just that its starting default is to assume you're rarely out |
|
466
|
of communication with the parent repo. |
|
467
|
<br><br> |
|
468
|
This is not merely a reflection of modern always-connected computing |
|
469
|
environments. It is a conscious decision in direct support of |
|
470
|
SQLite's cathedral development model: we don't want developers going |
|
471
|
dark, then showing up weeks later with a massive bolus of changes |
|
472
|
for us to integrate all at once. |
|
473
|
[https://en.wikipedia.org/wiki/Jim_McCarthy_(author)|Jim McCarthy] |
|
474
|
put it well in his book on software project management, |
|
475
|
<i>[https://www.amazon.com/dp/0735623198/|Dynamics of Software |
|
476
|
Development]</i>: "[https://www.youtube.com/watch?v=oY6BCHqEbyc|Beware |
|
477
|
of a guy in a room]." |
|
478
|
|
|
479
|
* <b>Branch names sync:</b> Unlike in Git, branch names in |
|
480
|
Fossil are not purely local labels. They sync along with everything |
|
481
|
else, so everyone sees the same set of branch names. Fossil's design |
|
482
|
choice here is a direct reflection of the Linux vs. SQLite project |
|
483
|
outlook: SQLite's developers collaborate closely on a single |
|
484
|
coherent project, whereas Linux's developers go off on tangents and |
|
485
|
occasionally send selected change sets to each other. |
|
486
|
|
|
487
|
* <b>Private branches are rare:</b> |
|
488
|
[/doc/trunk/www/private.wiki|Private branches exist in Fossil], but |
|
489
|
they're normally used to handle rare exception cases, whereas in |
|
490
|
many Git projects, they're part of the straight-line development |
|
491
|
process. |
|
492
|
|
|
493
|
* <b>Identical clones:</b> Fossil's autosync system tries to |
|
494
|
keep each local clone identical to the repository it cloned |
|
495
|
from. |
|
496
|
|
|
497
|
Where Git encourages siloed development, Fossil fights against it. |
|
498
|
Fossil places a lot of emphasis on synchronizing everyone's work and on |
|
499
|
reporting on the state of the project and the work of its developers, so |
|
500
|
that everyone — especially the project leader — can maintain a better |
|
501
|
mental picture of what is happening, leading to better situational |
|
502
|
awareness. |
|
503
|
|
|
504
|
By contrast, "…[https://docs.github.com/en/get-started/quickstart/contributing-to-projects|forking is |
|
505
|
at the core of social coding at GitHub]". As of January 2022, |
|
506
|
[https://github.com/search?q=is:public|Github hosts 47 million distinct |
|
507
|
software projects], most of which were created by forking a |
|
508
|
previously-existing project. Since this is |
|
509
|
[https://evansdata.com/reports/viewRelease.php?reportID=9 | roughly |
|
510
|
twice the number of developers in the world], it beggars belief that |
|
511
|
most of these forks are still under active development. The vast bulk |
|
512
|
of these must be abandoned one-off efforts. This is part of the nature |
|
513
|
of bazaar style development. |
|
514
|
|
|
515
|
You can think about this difference in terms of |
|
516
|
[https://en.wikipedia.org/wiki/Feedback | feedback loop size], which we |
|
517
|
know from the mathematics of |
|
518
|
[https://en.wikipedia.org/wiki/Control_theory | control theory] to |
|
519
|
directly affect the speed at which any system can safely make changes. |
|
520
|
The larger the feedback loop, the slower the whole system must run in |
|
521
|
order to avoid loss of control. The same concept shows up in other |
|
522
|
contexts, such as in the [https://en.wikipedia.org/wiki/OODA_loop | OODA |
|
523
|
loop] concept. |
|
524
|
Committing your changes to private branches in order to delay a public |
|
525
|
push to the parent repo increases the size of your collaborators' |
|
526
|
control loops, either causing them to slow their work in order to safely |
|
527
|
react to your work, or to over-correct in response to each change. |
|
528
|
|
|
529
|
Each DVCS can be used in the opposite style, but doing so works against |
|
530
|
their low-friction paths. |
|
531
|
|
|
532
|
|
|
533
|
<h4 id="scale">2.5.2 Scale</h4> |
|
534
|
|
|
535
|
The Linux kernel has a far bigger developer community than that of |
|
536
|
SQLite: there are thousands and thousands of contributors to Linux, most |
|
537
|
of whom do not know each other's names. These thousands are responsible |
|
538
|
for producing roughly 89× more code than is in SQLite. (10.7 |
|
539
|
[https://en.wikipedia.org/wiki/Source_lines_of_code|MLOC] vs. 0.12 MLOC |
|
540
|
according to [https://dwheeler.com/sloccount/|SLOCCount].) The Linux |
|
541
|
kernel and its development process were already uncommonly large back in |
|
542
|
2005 when Git was designed, specifically to support the consequences of |
|
543
|
having such a large set of developers working on such a large code base. |
|
544
|
|
|
545
|
95% of the code in SQLite comes from just four programmers, and 64% of |
|
546
|
it is from the lead developer alone. The SQLite developers know each |
|
547
|
other well and interact daily. Fossil was designed for this development |
|
548
|
model. |
|
549
|
|
|
550
|
When choosing your DVCS, we think you should ask yourself whether the |
|
551
|
scale of your software configuration management problems is closer to |
|
552
|
those Linus Torvalds designed Git to cope with or whether your work's |
|
553
|
scale is closer to that of SQLite, for which D. Richard Hipp designed |
|
554
|
Fossil. An [https://en.wikipedia.org/wiki/Impact_wrench|automotive air |
|
555
|
impact wrench] running at 8000 RPM driving an M8 socket-cap bolt at 16 |
|
556
|
cm/s is not the best way to hang a picture on the living room wall. |
|
557
|
|
|
558
|
Fossil works well for projects several times the size of SQLite, |
|
559
|
[https://core.tcl-lang.org/tcl/ | such as Tcl], with a repository over |
|
560
|
twice the size and with many more core committers. |
|
561
|
|
|
562
|
|
|
563
|
<h4 id="branches">2.5.3 Individual Branches vs. The Entire Change History</h4> |
|
564
|
|
|
565
|
Both Fossil and Git store history as a directed acyclic graph (DAG) |
|
566
|
of changes, but Git tends to focus more on individual branches of |
|
567
|
the DAG, whereas Fossil puts more emphasis on the entire DAG. |
|
568
|
|
|
569
|
For example, the default behavior in Git is to only synchronize |
|
570
|
a single branch, whereas with Fossil the only sync option is to |
|
571
|
sync the entire DAG. Git commands, |
|
572
|
GitHub, and GitLab tend to show only a single branch at |
|
573
|
a time, whereas Fossil usually shows all parallel branches at |
|
574
|
once. Git has commands like "rebase" that help keep all relevant |
|
575
|
changes on a single branch, whereas Fossil encourages a style of |
|
576
|
many concurrent branches constantly springing into existence, |
|
577
|
undergoing active development in parallel for a few days or weeks, then |
|
578
|
merging back into the main line and disappearing. |
|
579
|
|
|
580
|
This difference in emphasis arises from the different purposes of |
|
581
|
the two systems. Git focuses on individual branches, because that |
|
582
|
is exactly what you want for a highly-distributed bazaar-style project |
|
583
|
such as Linux. Linus Torvalds does not want to see every check-in |
|
584
|
by every contributor to Linux: such extreme visibility does not scale |
|
585
|
well. Contrast Fossil, which was written for the cathedral-style SQLite project |
|
586
|
and its handful of active committers. Seeing all |
|
587
|
changes on all branches all at once helps keep the whole team |
|
588
|
up-to-date with what everybody else is doing, resulting in a more |
|
589
|
tightly focused and cohesive implementation. |
|
590
|
|
|
591
|
Parts of this section are [https://fossil-scm.org/forum/forumpost/5961e969fa|disputed] |
|
592
|
by [https://github.com/olorin37|Jakub A. G.]. |
|
593
|
|
|
594
|
|
|
595
|
<h3 id="checkouts">2.6 One vs. Many Check-outs per Repository</h3> |
|
596
|
|
|
597
|
Because Git commingles the repository data with the initial checkout of |
|
598
|
that repository, the default mode of operation in Git is to stick to that |
|
599
|
single work/repo tree, even when that's a shortsighted way of working. |
|
600
|
|
|
601
|
Fossil doesn't work that way. A Fossil repository is an SQLite database |
|
602
|
file which is normally stored outside the working checkout directory. You can |
|
603
|
[/help/open | open] a Fossil repository any number of times into |
|
604
|
any number of working directories. A common usage pattern is to have one |
|
605
|
working directory per active working branch, so that switching branches |
|
606
|
is done with a <tt>cd</tt> command rather than by checking out the |
|
607
|
branches successively in a single working directory. |
|
608
|
|
|
609
|
Fossil does allow you to switch branches within a working checkout |
|
610
|
directory, and this is also often done. It is simply that there is no |
|
611
|
inherent penalty to either choice in Fossil as there is in Git. The |
|
612
|
standard advice is to use a switch-in-place workflow in Fossil when |
|
613
|
the disturbance from switching branches is small, and to use multiple |
|
614
|
checkouts when you have long-lived working branches that are different |
|
615
|
enough that switching in place is disruptive. |
|
616
|
|
|
617
|
While you can [./gitusers.md#worktree | use Git in the Fossil style], |
|
618
|
Git's default tie between working directory and |
|
619
|
repository means the standard method for working with a Git repo is to |
|
620
|
have one working directory only. Most Git tutorials teach this style, so |
|
621
|
it is how most people learn to use Git. Because relatively few people |
|
622
|
use Git with multiple working directories per repository, there are |
|
623
|
[https://duckduckgo.com/?q=git+worktree+problem | several known |
|
624
|
problems] with that way of working, problems which don't happen in Fossil because of |
|
625
|
the clear [./ckout-workflows.md | separation] between a Fossil repository and |
|
626
|
each working directory. |
|
627
|
|
|
628
|
This distinction matters because switching branches inside a single working directory loses local context |
|
629
|
on each switch. |
|
630
|
|
|
631
|
For instance, in any software project where the runnable program must be |
|
632
|
built from source files, you invalidate build objects on each switch, |
|
633
|
artificially increasing the time required to switch versions. Most obviously, this |
|
634
|
affects software written in statically-compiled programming languages |
|
635
|
such as C, Java, and Haskell, but it can even affect programs written in |
|
636
|
dynamic languages like JavaScript. A typical |
|
637
|
[https://en.wikipedia.org/wiki/Single-page_application | SPA] build |
|
638
|
process involves several passes: [http://browserify.org/ | Browserify] to convert |
|
639
|
[https://nodejs.org/ | Node] packages so they'll run in a web browser, |
|
640
|
[https://sass-lang.com | SASS] to CSS translation, |
|
641
|
transpilation of [https://www.typescriptlang.org | Typescript] to JavaScript, |
|
642
|
[https://github.com/mishoo/UglifyJS | uglification], etc. |
|
643
|
Once all that processing work is done for a given input |
|
644
|
file in a given working directory, why re-do that work just to switch |
|
645
|
versions? If most of the files that differ between versions don't change |
|
646
|
very often, you can save substantial time by switching branches with |
|
647
|
<tt>cd</tt> rather than swapping versions in-place within a working |
|
648
|
checkout directory. |
|
649
|
|
|
650
|
For another example, you might have an active long-running test grinding |
|
651
|
away in a working directory, then get a call from a customer requiring |
|
652
|
that you switch to a stable branch to answer questions in terms of the |
|
653
|
version that customer is running. You don't want to stop the test in |
|
654
|
order to switch your lone working directory to the stable branch. |
|
655
|
|
|
656
|
Disk space is cheap. Having several working directories — each with its |
|
657
|
own local state — makes switching versions cheap and fast. |
|
658
|
|
|
659
|
Plus, |
|
660
|
<tt>cd</tt> is faster to type than <tt>git checkout</tt> or <tt>fossil |
|
661
|
update</tt>. |
|
662
|
|
|
663
|
Parts of this section are [https://fossil-scm.org/forum/forumpost/5961e969fa|disputed] |
|
664
|
by [https://github.com/olorin37|Jakub A. G.]. |
|
665
|
|
|
666
|
<h3 id="history">2.7 What you should have done vs. What you actually did</h3> |
|
667
|
|
|
668
|
Git puts a lot of emphasis on maintaining |
|
669
|
a "clean" check-in history. Extraneous and experimental branches by |
|
670
|
individual developers often never make it into the main repository. |
|
671
|
Branches may be rebased before being pushed to make |
|
672
|
it appear as if development had been linear, or "squashed" to make it |
|
673
|
appear that multiple commits were made as a single commit. |
|
674
|
There are [https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History | |
|
675
|
other history rewriting mechanisms in Git] as well. Git strives to record what |
|
676
|
the development of a project should have looked like had there been no |
|
677
|
mistakes. |
|
678
|
|
|
679
|
Fossil, in contrast, puts more emphasis on recording exactly what happened, |
|
680
|
including all of the messy errors, dead-ends, experimental branches, and |
|
681
|
so forth. One might argue that this |
|
682
|
makes the history of a Fossil project "messy," but another point of view |
|
683
|
is that this makes the history "accurate." In actual practice, the |
|
684
|
superior reporting tools available in Fossil mean that this incidental mess |
|
685
|
is not a factor. |
|
686
|
|
|
687
|
Like Git, Fossil has an [/help/amend|amend command] for modifying |
|
688
|
prior commits, but unlike in Git, this works not by replacing data in |
|
689
|
the repository, but by adding a correction record to the repository that |
|
690
|
affects how later Fossil operations present the corrected data. The old |
|
691
|
information is still there in the repository, it is just overridden from |
|
692
|
the amendment point forward. |
|
693
|
|
|
694
|
Fossil lacks almost every other history rewriting mechanism listed on |
|
695
|
the Git documentation page linked above. [./rebaseharm.md | There is no |
|
696
|
rebase] in Fossil, on purpose, thus no way to reorder or copy commits |
|
697
|
around in the commit hash tree. There is no commit squashing, dropping, |
|
698
|
or interactive patch-based cherry-picking of commit elements in Fossil. |
|
699
|
There is nothing like Git's <tt>filter-branch</tt> in Fossil. |
|
700
|
|
|
701
|
The lone exception is deleting commits. Fossil has two methods for doing |
|
702
|
that, both of which have stringent limitations, on purpose. |
|
703
|
|
|
704
|
The first is [/doc/trunk/www/shunning.wiki | shunning]. See that |
|
705
|
document for details, but briefly, you only get mandatory compliance |
|
706
|
for shun requests within a single repository. Shun requests do not |
|
707
|
propagate automatically between repository clones. A Fossil repository |
|
708
|
administrator can <i>cooperatively</i> pull another repo's shun requests |
|
709
|
across a sync boundary, so that two admins can get together and agree to |
|
710
|
shun certain committed artifacts, but a person cannot force their local |
|
711
|
shun requests into another repo without having admin-level control over |
|
712
|
the receiving repo as well. Fossil's shun feature isn't for fixing up |
|
713
|
everyday bad commits, it's for dealing with extreme situations: public |
|
714
|
commits of secret material, ticket/wiki/forum spam, law enforcement |
|
715
|
takedown demands, etc. |
|
716
|
|
|
717
|
There is also the experimental [/help/purge | <tt>purge</tt> |
|
718
|
command], which differs from shunning in ways that aren't especially |
|
719
|
important in the context of this document. At a 30000 foot level, you |
|
720
|
can think of purging as useful only when you've turned off Fossil's |
|
721
|
autosync feature and want to pluck artifacts out of its hash tree before |
|
722
|
they get pushed. In that sense, it's approximately the same as |
|
723
|
<tt>git rebase -i, drop</tt>. However, given that Fossil defaults to |
|
724
|
having autosync enabled [#devorg | for good reason], the purge command |
|
725
|
isn't very useful in practice: once a commit has been pushed into |
|
726
|
another repo, shunning is more useful if you need to delete it from |
|
727
|
history. |
|
728
|
|
|
729
|
If these accommodations strike you as incoherent with respect to |
|
730
|
Fossil's philosophy of durable, unchanging commits, realize that if |
|
731
|
shunning and purging were removed from Fossil, you could still remove |
|
732
|
artifacts from the repository with SQL <tt>DELETE</tt> statements; the |
|
733
|
repository database file is, after all, directly modifiable, being |
|
734
|
writable by your user. Where the Fossil philosophy really takes hold is |
|
735
|
in making it difficult to violate the integrity of the hash tree. |
|
736
|
It's somewhat tangential, but the document [./blockchain.md | "Is Fossil |
|
737
|
a Blockchain?"] touches on this and related topics. |
|
738
|
|
|
739
|
One commentator characterized Git as recording history according to |
|
740
|
the victors, whereas Fossil records history as it actually happened. |
|
741
|
|
|
742
|
|
|
743
|
<h3 id="testing">2.8 Test Before Commit</h3> |
|
744
|
|
|
745
|
One of the things that falls out of Git's default separation of commit |
|
746
|
from push is that there are several Git sub-commands that jump straight |
|
747
|
to the commit step before a change could possibly be tested. Fossil, by |
|
748
|
contrast, makes the equivalent change to the local working check-out |
|
749
|
only, requiring a separate check-in step to commit the change. This |
|
750
|
design difference falls naturally out of Fossil's default-enabled |
|
751
|
autosync feature and its philosophy of [#history | not offering history |
|
752
|
rewriting features]. |
|
753
|
|
|
754
|
The prime example in Git is rebasing: the change happens to the local |
|
755
|
repository immediately if successful, even though you haven't tested the |
|
756
|
change yet. It's possible to argue for such a design in a tool like Git |
|
757
|
since it lacks an autosync feature, because you can still test the |
|
758
|
change before pushing local changes to the parent repo, but in the |
|
759
|
meantime you've made a durable change to your local Git repository. You |
|
760
|
must do something drastic like <tt>git reset --hard</tt> to revert that |
|
761
|
rebase or rewrite history before pushing it if the rebase causes a |
|
762
|
problem. If you push your rebased local repo up to the parent without |
|
763
|
testing first, you cannot fix it without violating |
|
764
|
[https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing |
|
765
|
| the golden rule of rebasing]. |
|
766
|
|
|
767
|
Lesser examples are the Git <tt>merge</tt>, <tt>cherry-pick</tt>, and |
|
768
|
<tt>revert</tt> commands, all of which apply work from one branch onto |
|
769
|
another, and all of which commit their change to the local repository |
|
770
|
immediately without giving you |
|
771
|
an opportunity to test the change first unless you give the |
|
772
|
<tt>--no-commit</tt> option. Otherwise, you're back in the same boat: |
|
773
|
reset the local repository or rewrite history to fix things, then maybe |
|
774
|
retry. |
|
775
|
|
|
776
|
Fossil cannot sensibly work that way because of its default-enabled |
|
777
|
autosync feature and its purposeful paucity of commands for modifying |
|
778
|
commits, as discussed in [#history | the prior section]. |
|
779
|
|
|
780
|
Instead of jumping straight to the commit step, Fossil |
|
781
|
applies the proposed merge to the local working directory only, |
|
782
|
requiring a separate check-in step before the change is committed to the |
|
783
|
repository. This gives you a chance to test the change first, |
|
784
|
either manually or by running your software's automatic tests. (Ideally, |
|
785
|
both!) Thus, Fossil doesn't need rebase, squashing, |
|
786
|
<tt>reset --hard</tt>, or other Git commit mutating mechanisms. |
|
787
|
|
|
788
|
Because Fossil requires an explicit commit for a merge, it has the nice |
|
789
|
side benefit that it makes you give an explicit commit <i>message</i> |
|
790
|
for each merge, whereas Git writes that commit message itself by default |
|
791
|
unless you give the optional <tt>--edit</tt> flag to override it. |
|
792
|
|
|
793
|
We don't look at this difference as a workaround in Fossil for autosync, |
|
794
|
but instead as a test-first philosophical difference: |
|
795
|
<tt>fossil commit</tt> is a <i>commitment</i>. When every commit is |
|
796
|
pushed to the parent repo by default, it encourages a working style in |
|
797
|
which every commit is tested first. It encourages thinking before |
|
798
|
acting. We believe this is an inherently good thing. |
|
799
|
|
|
800
|
Incidentally, this is a good example of Git's messy command design. |
|
801
|
These three commands: |
|
802
|
|
|
803
|
<pre> |
|
804
|
$ git merge HASH |
|
805
|
$ git cherry-pick HASH |
|
806
|
$ git revert HASH |
|
807
|
</pre> |
|
808
|
|
|
809
|
...are all the same command in Fossil: |
|
810
|
|
|
811
|
<pre> |
|
812
|
$ fossil merge HASH |
|
813
|
$ fossil merge --cherrypick HASH |
|
814
|
$ fossil merge --backout HASH |
|
815
|
</pre> |
|
816
|
|
|
817
|
If you think about it, they're all the same function: apply work done on |
|
818
|
one branch to another. All that changes between these commands is how |
|
819
|
much work gets applied — just one check-in or a whole branch — and the |
|
820
|
merge direction. This is the sort of thing we mean when we point out |
|
821
|
that Fossil's command interface is simpler than Git's: there are fewer |
|
822
|
concepts to keep track of in your mental model of Fossil's internal |
|
823
|
operation. |
|
824
|
|
|
825
|
Fossil's implementation of the feature is also simpler to describe. The |
|
826
|
brief online help for <tt>[/help/merge | fossil merge]</tt> is |
|
827
|
currently 41 lines long, to which you want to add the 600 lines of |
|
828
|
[./branching.wiki | the branching document]. The equivalent |
|
829
|
documentation in Git is the aggregation of the man pages for the above |
|
830
|
three commands, which is over 1000 lines, much of it mutually redundant. |
|
831
|
(e.g. Git's <tt>--edit</tt> and <tt>--no-commit</tt> options get |
|
832
|
described three times, each time differently.) Fossil's |
|
833
|
documentation is not only more concise, it gives a nice split of brief |
|
834
|
online help and full online documentation. |
|
835
|
|
|
836
|
|
|
837
|
<h3 id="hash">2.9 Hash Algorithm: SHA-3 vs SHA-2 vs SHA-1</h3> |
|
838
|
|
|
839
|
Fossil started out using 160-bit SHA-1 hashes to identify check-ins, |
|
840
|
just as in Git. That changed in early 2017 when news of the |
|
841
|
[https://shattered.io/|SHAttered attack] broke, demonstrating that SHA-1 |
|
842
|
collisions were now practical to create. Two weeks later, the creator of |
|
843
|
Fossil delivered a new release allowing a clean migration to |
|
844
|
[https://en.wikipedia.org/wiki/SHA-3|256-bit SHA-3] with |
|
845
|
[./hashpolicy.wiki|full backwards compatibility] to old SHA-1 based |
|
846
|
repositories. |
|
847
|
|
|
848
|
In October 2019, after the last of the major binary |
|
849
|
package repos offering Fossil upgraded to Fossil 2.<i>x</i>, |
|
850
|
we switched the default hash mode so that |
|
851
|
the conversion to SHA-3 is fully automatic. |
|
852
|
This not |
|
853
|
only solves the SHAttered problem, it should prevent a reoccurrence of |
|
854
|
similar problems for the foreseeable future. |
|
855
|
|
|
856
|
Meanwhile, the Git community took until August 2018 to publish |
|
857
|
[https://git-scm.com/docs/hash-function-transition/|their first plan] |
|
858
|
for solving the same problem by moving to SHA-256, a variant of the |
|
859
|
[https://en.wikipedia.org/wiki/SHA-2 | older SHA-2 algorithm]. As of |
|
860
|
this writing in February 2020, that plan hasn't been implemented, as far |
|
861
|
as this author is aware, but there is now |
|
862
|
[https://lwn.net/ml/git/[email protected]/ |
|
863
|
| a competing SHA-256 based plan] which requires complete repository |
|
864
|
conversion from SHA-1 to SHA-256, breaking all public hashes in the |
|
865
|
repo. One way to characterize such a massive upheaval in Git terms is a |
|
866
|
whole-project rebase, which violates the |
|
867
|
[https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing|Golden Rule of Rebasing]. |
|
868
|
|
|
869
|
Regardless of the eventual implementation details, we fully expect Git |
|
870
|
to move off SHA-1 eventually and for the changes to take years more to |
|
871
|
percolate through the community. |
|
872
|
|
|
873
|
Almost three years after Fossil solved this problem, the |
|
874
|
[https://sha-mbles.github.io/ | SHAmbles attack] was published, further |
|
875
|
weakening the case for continuing to use SHA-1. |
|
876
|
|
|
877
|
The practical impact of attacks like SHAttered and SHAmbles on the |
|
878
|
Git and Fossil Merkle trees isn't clear, but you want to have your repositories |
|
879
|
moved over to a stronger hash algorithm before someone figures out how |
|
880
|
to make use of the weaknesses in the old one. Fossil has had this covered |
|
881
|
for years now, so that the solution is now almost universally deployed. |
|
882
|
|
|
883
|
<hr/> |
|
884
|
|
|
885
|
<h3>Asides and Digressions</h3> |
|
886
|
|
|
887
|
<i><small><ol> |
|
888
|
<li><p>[./mirrorlimitations.md|Many |
|
889
|
things are lost] in making a Git mirror of a Fossil repo due to |
|
890
|
limitations of Git relative to Fossil. GitHub adds some of these |
|
891
|
missing features to stock |
|
892
|
Git, but because they're not part of Git proper, |
|
893
|
[./mirrortogithub.md|exporting a Fossil repository to GitHub] will |
|
894
|
still not include them; Fossil tickets do not become GitHub issues, |
|
895
|
for example. |
|
896
|
|
|
897
|
<li><p>The <tt>fossil-scm.org</tt> web site is actually hosted in |
|
898
|
several parts, so that it is not strictly true that "everything" on |
|
899
|
it is in the self-hosting Fossil project repo. The web forum is |
|
900
|
hosted as [https://fossil-scm.org/forum/|a separate Fossil repo] |
|
901
|
from the [https://fossil-scm.org/home/|main Fossil self-hosting |
|
902
|
repo] for administration reasons, and the Download page content |
|
903
|
isn't normally synchronized with a "<tt>fossil clone</tt>" command unless |
|
904
|
you add the "-u" option. (See "[./aboutdownload.wiki|How the |
|
905
|
Download Page Works]" for details.) |
|
906
|
Chat history is deliberately not synced as |
|
907
|
chat messages are intended to be ephemeral. |
|
908
|
There may also be some purely |
|
909
|
static elements of the web site served via D. Richard Hipp's own |
|
910
|
lightweight web server, |
|
911
|
<tt>[https://sqlite.org/althttpd/|althttpd]</tt>, |
|
912
|
which is configured as a front end to Fossil running in CGI mode on |
|
913
|
these sites. |
|
914
|
|
|
915
|
<li><p>That estimate is based on pricing at Digital Ocean in |
|
916
|
mid-2019: Fossil will run just fine on the smallest instance they |
|
917
|
offer, at US $5/month, but the closest match to GitLab's minimum |
|
918
|
requirements among Digital Ocean's offerings currently costs |
|
919
|
$40/month. |
|
920
|
|
|
921
|
<li><p>This means you can give up waiting for Fossil to be ported to |
|
922
|
the PDP-11, but we remain hopeful that someone may eventually port |
|
923
|
it to [https://en.wikipedia.org/wiki/Z/OS|z/OS]. |
|
924
|
|
|
925
|
<li><p>"Why is there all this Tcl in and around Fossil?" you may |
|
926
|
ask. It is because D. Richard Hipp is a long-time Tcl user and |
|
927
|
contributor. SQLite started out as an embedded database for Tcl |
|
928
|
specifically. ([https://sqlite.org/tclsqlite.html | [Reference]]) |
|
929
|
When he then created Fossil to manage the development of SQLite, it |
|
930
|
was natural for him to use Tcl-based tools for its scripting, build |
|
931
|
system, test system, etc. It came full circle in 2011 when |
|
932
|
[https://www.reddit.com/r/programming/comments/fwrx5/tcl_and_tk_move_away_from_cvs_to_fossil/ |
|
933
|
| the Tcl and Tk projects moved from CVS to Fossil]. |
|
934
|
|
|
935
|
<li><p>A minority of the pieces of the Git core software suite are |
|
936
|
written in other languages, primarily Perl, Python, and Tcl. (e.g. |
|
937
|
<tt>git-send-mail</tt>, <tt>git-p4</tt>, and <tt>gitk</tt>, |
|
938
|
respectively.) Although these interpreters are quite portable, they |
|
939
|
aren't installed by default everywhere, and on some platforms you |
|
940
|
can't count on them at all. (Not just Windows, but also the BSDs and |
|
941
|
many other non-Linux platforms.) This expands the dependency |
|
942
|
footprint of Git considerably. It is why the current Git for Windows |
|
943
|
distribution is 44.7 MiB but the current <tt>fossil.exe</tt> |
|
944
|
zip file for Windows is 2.24 MiB. Fossil is much smaller |
|
945
|
despite using a roughly similar amount of high-level scripting code |
|
946
|
because its interpreters are compact and built into Fossil itself. |
|
947
|
|
|
948
|
<li><p>Both Fossil and Git support |
|
949
|
[https://en.wikipedia.org/wiki/Patch_(Unix)|<tt>patch(1)</tt> |
|
950
|
files] — unified diff formatted output — for accepting drive-by contributions, but it's a |
|
951
|
lossy contribution path for both systems. Unlike Git PRs and Fossil |
|
952
|
bundles, patch files collapse multiple checkins together, they don't |
|
953
|
include check-in comments, and they cannot encode changes made above |
|
954
|
the individual file content layer: you lose branching decisions, |
|
955
|
tag changes, file renames, and more when using patch files. The |
|
956
|
[./patchcmd.md | <tt>fossil patch</tt> command] |
|
957
|
also solves these problems, but it is because it works like a Fossil |
|
958
|
bundle, only for uncommitted changes; it doesn't use Larry Wall's |
|
959
|
<tt>patch</tt> tool to apply unified diff output to the receiving |
|
960
|
Fossil checkout.</p></li> |
|
961
|
</ol></i></small> |
|
962
|
|