- SQLiteのソースコードはGitではなくFossilで管理されており、FossilはSQLiteを支援するために特別に設計・作成されたバージョン管理システム
- Fossilは、単一画面で全ブランチの最近の変更を表示する**状況認識(situational awareness)**機能を提供し、スマートフォンからもアクセス可能
- Gitはチェックインの過去の履歴だけを追跡し、その後の後続(descendents)追跡が難しい一方、Fossilは後続チェックインと分岐構造を簡単に表示
- Gitでは作業ディレクトリ、ステージング、ローカル/リモートheadなど5つの状態を意識する必要があるが、Fossilでは作業ディレクトリとチェックインだけを考えればよく、負担が60%少ない
- Gitに慣れたユーザーも、GitHubミラー、Webダウンロード、Fossilのインストールなどを通じてSQLiteのソースに同じようにアクセス可能
概要と本稿の前提
- SQLiteはGitの代わりにFossilを使っており、FossilはSQLiteを支援する目的で直接作られたバージョン管理システム
- 本稿はFossilとGitの比較ではなく、Gitの利用停止を勧めるものでもない
- Gitに満足しているなら、そのまま使い続けても差し支えない
- Gitが合わない、または改善や代替を検討している場合に参考となる視点を提示する
- この文書は明確さの改善と誤りの修正のために何度も改訂されており、全編集履歴を閲覧可能
SQLiteがGitを使わない理由
Gitは優れた状況認識を提供しない
- Fossilのtimelineは、単一画面で全ブランチの最近の変更概要を提供し、数クリックで詳細まで確認でき、スマートフォンでも利用可能
- GitHubやGitLabには、これに匹敵する機能がない
- networkビューはレンダリングが遅く(キャッシュ前基準)、詳細情報が少なく、モバイルではほとんど動作しない
- commitsビューは高速でモバイルでも動作するが、一度に単一ブランチしか表示しないため、すべての変更を確認したかどうか分かりにくい
- GitHubやGitLabはGitの中核構成要素ではないサードパーティサービスであり、追加の依存関係を生む
- Gitユーザーはサードパーティ製のグラフィカルビューアをインストールすることが多いが、これは別途インストールと管理が必要で、プラットフォームに依存する
- 優れたツールの一つであるGitUpはMacでしか動作しない
- どのツールもローカルリポジトリの同期後にデスクトップGUIを起動する必要があり、外出先でスマートフォンからプロジェクトの状態を確認することはできない
Gitではチェックインの後続(子孫)を見つけにくい
- Gitでは過去を振り返ることはできるが、その後に進んだ履歴を追跡するのは難しい
- 特定の過去のチェックインについて、それ以前の履歴は見えるが、その後に何が来たかを確認するのは面倒
- Fossilは、最新メジャーリリースから派生したすべてのチェックインを表示する画面を提供する
- Gitでも子孫探しが不可能というわけではないが難しい
- stackoverflowにはUnix向けのコマンド列が存在するが、このコマンドは分岐構造なしに子孫リストだけを出力する
- そのコマンドはローカルクローンがある場合にのみ動作し、GitHubやGitLabのようなWebインターフェースでは子孫を確認できない
- Fossilでは子孫情報がWebページ全体に反映される
- すべてのチェックイン情報ページに、直前・直後のチェックインを示す小さな**「Context」グラフ**を表示
- 次のチェックインへクリックで移動するなど、状況認識を助ける機能を提供
- Gitでも適切な拡張、ツール、コマンドを使えば理論上は可能だが簡単ではないため、ほとんど行われず、その結果として開発者のコード変更に対する認知度が下がる
Gitのメンタルモデルは不必要に複雑
- Gitユーザーは次の5つを常に意識する必要がある
- 作業ディレクトリ(working directory)
- 「index」またはステージング領域
- ローカルhead
- リモートheadのローカルコピー
- 実際のリモートhead
- Fossilユーザーは作業ディレクトリと作業中のチェックインだけを考えればよく、これは注意の分散が60%少ない
- 開発者の限られた集中力(brain-cycles)を節約し、開発中のソフトウェアに集中できるよう支援する
- GitとFossilの両方を使うあるユーザーはHNで、「Fossilは単一のコマンドですべてがサーバーに同期されたという安心感を与えてくれるが、gitではその安心感を得られない」と述べた
Gitは過去のブランチ名を追跡しない
- Gitはチェックイン列の完全なDAGを保持するが、ブランチタグはローカル情報で同期されず、ブランチが閉じられると保持されないため、過去のブランチを確認するのが煩雑
- 例:2年前の「prefer-coroutine-sort-subquery」ブランチの行方を尋ねる場合
- Fossil:そのブランチが最終的にtrunkへマージされた事実、開始地点、trunkの変更がブランチへ2回マージされた状況を明確に表示
- GitHub:こうした情報をまったく示せず、何が起きたのか把握するうえで事実上役に立たない
- サードパーティ製GUIのほうが優れている可能性はあるが、Gitが同期時に過去のブランチ名を保存しないという制約に縛られる
- 望む情報を得るためにサードパーティツールが必要であること自体が、中核システムの弱点
Gitはより多くの管理支援を必要とする
- Gitは複雑なソフトウェアで、ワークステーションへのインストールやアップグレードにはインストーラが必要であり、Gitサーバーの構築も簡単ではない
- ほとんどの場合、GitHubやGitLabのようなサードパーティサービスを使うため、追加の依存関係が発生する
- Fossilは**$PATHに置けばインストール完了となる単一の独立実行バイナリ**
- この1つのバイナリが、中核GitとGitHub・GitLabの機能をすべて含む
- Wiki、バグ追跡、フォーラムを備えたコミュニティサーバーの管理、パッケージダウンロードの提供、ログイン管理などを追加ソフトウェアなしで実行
- コミュニティサーバーの構築にかかるのは数分
- 月額5ドルのVPSやRaspberry Piでも快適に動作する一方、GitLabなどはより高いスペックを要求する
- 管理負担が少ないほど、開発者はバージョン管理システムではなくソフトウェア(SQLite)の作業により多くの時間を投入できる
Gitは良くないユーザー体験を提供する
- xkcd 1597の漫画は誇張だが、現実に近い
- Gitが次善のユーザー体験を提供している点について異論は少なく、内部実装がインターフェースとしてそのまま露出している
- 偽のgit manページを生成するパロディサイトが存在するほど、インターフェースが劣悪
- 優れたバージョン管理システムはフラストレーションではなく支援を提供すべきであり、Gitは過去10年で改善されたものの、まだ道半ば
Gitユーザー向けSQLiteソースコードアクセスガイド
公式GitHubミラー
- 2019-03-20から、GitHub上にSQLiteソースの公式Gitミラーが存在する
- 正式なFossilリポジトリの増分エクスポートで、cronジョブが1時間に1回GitHubリポジトリを更新する
- 一方向・読み取り専用ミラーで、pull requestや変更は受け付けない
- すべての変更はFossil経由でのみ入力される
- チェックインやファイル識別ハッシュは、GitミラーとFossilで互いに異なる
- 主な理由は、FossilがSHA3-256、GitがSHA1ハッシュを使用するため
- エクスポート時に元のFossilハッシュがチェックインコメントのフッターとして追加され、SQLiteのチェックインを参照する際は混同を避けるため、常に元のFossilハッシュを使うことを推奨
Webアクセス
- SQLiteのFossilリポジトリは、任意の過去バージョンについてTarball、ZIP Archive、SQLite Archiveのダウンロードリンクを提供する
- URL形式が単純なため、自動化ツールへ簡単に統合可能
Fossilアクセス
- Fossilはインストールも使用も簡単で、Unix基準の手順を提供(Windowsも類似)
- fossil実行ファイルをダウンロードして$PATHに配置
fossil cloneでリポジトリを複製し、fossil openで開く
- その後、
./configure; make(Windows MSVCではnmake /f Makefile.msc)を実行可能
fossil update VERSIONコマンドで別バージョンへチェックアウトを変更(VERSIONにはtrunk、ハッシュ接頭辞、ブランチ・タグを使用)
- チェックアウト内で
fossil uiコマンドを実行するとローカルWebサイトが起動する
- ログインなしでは変更をpushできず、プロジェクトを損傷させることができないため、自由に探索・実験できる
ソースコードの完全性検証
- ソースツリーのルートに**「manifest」**ファイルが存在する
- このファイルはすべてのファイル名と各ファイルのSHA1またはSHA3-256ハッシュを含む(古いファイルはSHA1、新しいファイルはSHA3-256)
- スクリプトでハッシュを抽出し、ソースファイルと照合して検証可能
- チェックインのハッシュ名は「manifest」ファイル自体のSHA3-256ハッシュであり、最終行が「# Remove this line...」で始まる場合は、その行を省略可能
1件のコメント
Hacker Newsのコメント
何十年も使ってきたバージョン管理ツールと、その登場年、最後に使った年を整理してみた: sccs 1973~2000, rcs 1982~2000, cvs 1990~2004, clearcase 1992~2004, perforce 1995~2011, subversion 2000~2015, mercurial 2005~2015, git 2005~現在
少なくとも自分にとって、こうしたツールの寿命はだいたい15年くらいだった
それなのにジュニアに「君たちが自分くらいの年齢になるころには、gitは遠くて奇妙な記憶になっているだろう」と言うと、変な目で見られる
gitは素晴らしいツールで、成功するだけの価値があったが、この問題がgitで終わるのだとしたら少し残念に思う
Joel on Softwareには、ソフトウェアはだいたい4バージョンくらいでほぼ完成する、という話があり、例として挙げられていたのはオフィスソフト、とくにExcelだった
今Excel 4を起動しても、基本機能は本質的にすべて備わっているという点で、その指摘は当たっているように思える
gitは以前のバージョン管理ツールより少なくとも2倍は長生きしそうだ
問題は、CVSが分散開発モデルへ拡張できない袋小路だったことにある
GitはローカルRCSモデルに立ち戻り、そこへアトミックコミットを加えることで、Subversionという局所最適から抜け出した
リネーム追跡をしない、線形リビジョン番号がない、といった議論を呼ぶ選択もあったが大きな問題にはならず、darcsのような性能問題もなく非常に効率的な作業を可能にした
1995~2010年の間にバージョン管理を改善しようとする試みが数多くあったことを考えると、gitの基本データモデルは、git-lfsのような追加機能まで含めて、改良するのが非常に難しいように見える
新しいコマンドラインインターフェースは出てくるかもしれないが、既存の覇者を押しのけるのはますます難しくなっており、過負荷で紛らわしい
git checkoutの代わりにgit switchやgit restoreを使っている人は周囲にいない会社の別の部署には少しsvnもあったが、その程度だった
バージョン管理システムはそう簡単には変わらない
分散バージョン管理が登場する前の一覧にあるツールは、実際には共通点が多く、gitはかなり長く残りそうだ
歴史的にはさまざまな言語が支配的だったが英語が最終的な言語になり、さまざまなスクリプト言語があったがjavascriptが最終的な言語になり、さまざまなネットワークプロトコルがあったがTCP/IPが最終的なプロトコルになるだろう
gitも同じだと思う
gitを押しのけられるとしたら、glitch[1]のように、新しいプログラマー向け環境に独自のバージョン管理システムが付属している場合くらいだろう
[1]: https://medium.com/glitch/reinventing-version-control-with-g...
gitの評判が悪い理由は、誰も使い方に合意できていないからだと思う
GitHub PRとブランチへのプッシュ、rebaseとmergeを見ても、本質的には同じことをまったく異なるやり方で行う道具になっている
問題は、どちらも間違いではないことだ
小さなコミットをrebaseすれば履歴の不要な複雑さは減り、mergeは実際に何が起きたかを保持するので、変更理由の理解に役立つ
もちろん逆方向のmergeは最悪だが、それはまた別の厄介事だ
ブランチにプッシュするときはforce pushを絶対にしないようにもできるが、PRブランチにはいつもforce pushすることになる
さらに簡単なことですら、埋めがたい亀裂を生む
自分はメインのリポジトリをorigin、自分のフォークをforkと教わったが、メインのリポジトリをupstream、自分のフォークをoriginと教わる人もいる
どちらも必ずしも間違いではないが、originがまったく別の2つの場所を指しうるなら、明確にコミュニケーションするのは非常に難しい
実際には、PR内のコミットは「何をすればレビューが最もしやすくなるか」だけに集中して積極的にrebaseする
レビューが終わったら、「今後、運用と理解が最もしやすい形は何か」を問い、全部squashすることもあれば、ロールバックしやすいように独立デプロイ可能な単位へ再構成することもある
要点は、こうした作業は互いに異なる要件を持ちうるし、時点ごとに異なるやり方を使っても構わないということだ
ただし、個人の判断力がより必要になり、大きなチーム全体に教えて徹底させるのは難しい
前者は他人に影響しないものだ
たとえば、リモートリポジトリ名を
originとupstreamにするか、forkとoriginにするかは同僚には関係ない後者は他の人と調整しなければならないものだ
たとえば最終的なgit履歴をどんな形で残すか、といった問題である
もしAppleがgitのコマンドラインインターフェースを設計していたら、ユーザー体験の面では10億倍よくなって、強力さは10%くらいしか失われなかったと思う
Fossilが彼らに合っているのは良いことだが、この一文は引っかかる: 「Fossilは
$PATHに置くだけでインストールできる単一のスタンドアロン実行バイナリで、その1つの中にGitの中核機能とGitHub/GitLabの機能がすべて入っている…」Gitにはいろいろ問題があっても、台所の流しまで全部ひとまとめにするようなものではない。
私は「1つのことをうまくやる」アプローチのほうが良いと思う。
たとえば
git instawebを実行すると、ローカルのCGIサーバーとPerl CGIスクリプトを立ち上げて、ごく単純なWeb UIを提供する: https://git-scm.com/docs/git-instawebこの点ではFossilの中核機能と大して変わらない。
GitHubしか使わない人は、おそらく存在すら、ましてなぜあるのかも知らない メールクライアント連携 機能もGitには多い。
git send-emailのように、Gitから直接メールパッチを送るものだ: https://git-scm.com/docs/git-send-emailすべては複合物であり、すべてはコマンドのパイプラインであり、複数のものからできている。
「やるべきこと」は絶対的なものではなく、それを見る人の視点に依存する。
単一責任の原則 は現実にそのまま適用されるものではなく、凝集性とモジュール性のバランスを保つための折衷にすぎない。
どこで切って「1つ」と呼ぶかは、私たちと私たちの必要次第だ。
多くの人にとってGitHubのツール群はワークフローに深く統合されすぎていて、Gitだけではまったく使いものにならない。
彼らにとってはGitHubが「1つのこと」であり、SQLiteにはSQLiteなりの「1つのこと」があるということだ。
言うとおり、それは1つのことをうまくやれというUnix哲学に反している。
私にとっては、あとで独立して置き換えたり修正したりできるコンポーネントにシステムを分けるほうが、明らかにすっきりしている。
インストーラーは50MBを超え、記憶が正しければターミナルまで含まれている。
一方Fossilは、対応プラットフォームごとに3.3MBのスタンドアロン実行バイナリをダウンロードできる。
https://git-man-page-generator.lokaltog.net は、ここしばらく見たものの中でいちばん笑った。
git-erase-working-treeの説明が「upstreamルートと設定の現在のワーキングツリーを注意深く消去し、アクティブなGUIでquiltimportしたいときに使うべき」となっていて、有用そうに見える。git-molest-headが「リモートインデックスを使ってupstreamヘッドを誤っていたぶり、与えられたヘッドを表にするため適切なフックを実行する」となっていて、ちょっと刺激が強すぎる。Gitには変なコマンドがあるので、もはや驚きもしない。
git-tease-chain、git-scrub-dangling-object、git-seize-mailmap、git-dress-graft、git-strangle-tree、git-satisfy-daemon、git-pat-tree-object。もっとそれっぽいナンセンスにするには、LLMの味付けがさらに必要だ。
以前の議論:
2021年、コメント356件: https://news.ycombinator.com/item?id=29125934
2018年、コメント608件: https://news.ycombinator.com/item?id=16806114
もっとあるはずだが、同じ文書が
wwwドメインなしでも、/drafts/パスなしでも、/matrix/パスなしでも複数の経路で見つかるため、以前の投稿を探すのがさらに難しくなっている。ここにはGitに対するもっともな批判もあるが、いくつかは少し妙だ。
ローカルの個人リポジトリから非常に大きな会社のリポジトリまでさまざまな状況でGitを使ってきたが、正直これらの問題の半分ほどは経験したことがない。
「networkはレンダリングが遅く、詳細情報がはるかに少なく、モバイルではほとんど動かない」という部分もそうだし、うちのチームがブランチの状態を確認する手段としてモバイル端末を考慮しなければならない日が来ないことを願う。
そんなユースケースは考えたこともない。
他の人にはよくあることなのか?
コード探索の少なくとも50%はスマホでやっている気がする。
そのためにモバイル版のGitHub Webインターフェースをよく使っていて、参照先検索のサポートは本当に大きな助けになった。
検索はまだいまひとつで、SPA特有のもたつきで標準のページ内検索を何度も壊してしまうのは嫌だ。
Firefoxのコードを掘る必要があるときはSearchfox [0]を使っているが、高速で素晴らしく、ほとんど不満はない。
ただ、モバイルでのblameはもう少し改善の余地がある。
背景を補足すると、私は大学院生で、プログラミング言語とシステムの研究をしており、個人の時間にはIoTハッキングもかなりやっている。
世代の区切りをどこに置くかによって、年長のGen Zか、あり得る限り最年少のMillennialということになる。
[0] https://searchfox.org
データ通信の安定性が低いことを除けばGitHubはちゃんと動いたし、軽いコードレビューも簡単にできた。
GitHub pulse[1]は最近の活動を見るのに良いUIだ。
SQLiteのミラーはGitHub上で作業されていないのでコミット履歴しかなく、このページは空だが、リンクされているCaddyプロジェクトのほうがよい例だ。
個人的にはタイムラインより有用に見える。
git/GitHub向けに同等のビューをすでに作った人がいるのか気になる。
それほど難しくはなさそうだ。
[1] https://github.com/caddyserver/caddy/pulse
GitHub上で編集するためにAndroidエディタを作り、その後GitLabでも動くように修正した。
理由はいろいろあるが、大半はgitがGitHubであれGitLabであれモバイルではほとんど使えないからだ。
状態確認はできるが、それ以上はほぼ難しい。
この文章はほかの面でもとても共感できた。
GitHubに関するO’Reillyの本を書いたのに、gitを10年以上使っていてもまだ完全には理解できていない気がする。
ここでの指摘には共感する。
もっとよく設計・実装されていれば、当然モバイルでも動いていたはずだ。
人々がモバイルでもGitHubに頻繁にアクセスするのは、ほかのプラットフォームからGitHubにアクセスするのと同じ理由からだ。
私も確かにやったことがある。
gitについてのこうした観察は、必ずしも「問題」というより機能に対する価値判断に近い。
同意することも反対することもできるが、必ず直面しなければならない種類のものではない。
漸進的な性能低下と即時失敗の違いに当たるように思う。
きちんとした豪華な選択肢がどれだけ優れていても、それが唯一の選択肢なら脆弱であり、だからこそ駄目になる。
数日前にGitの代替を説明する動画を見たが、Fossilももちろんその1つだった。
いくつかのプロジェクトでFossilを使ったことがあるが、悪くなかった。
この発表で説明されていたPijul https://pijul.org/は非常に興味深く、HNでも以前議論されたことがある。
出典: https://www.youtube.com/watch?v=M4KktA_jbOE
バージョン管理の聖杯のように感じる。
ただ、個人プロジェクトではどうせ一直線に開発するし、仕事で何を使うかは自分ではコントロールできないので、実際に使ったことはない。
個人のローカルプロジェクトで Fossil を使ってみたことがある
かなり有能なバージョン管理システムで、Web UI も相当に良い
ただし注意点として、基盤となる SQLite リポジトリデータベース を頻繁にバックアップしておくべきだ
Fossil をアップグレードして何度かコミットしたあと、誤ってさらに古い Fossil バージョンでコミットしてしまったところ、Fossil リポジトリデータベースが復旧不能なほど壊れ、数日分の作業を失った
10年間毎日使っていても、Git がバージョンに関係なくリポジトリを壊したことは一度もなかった
何年も差のあるバージョンが異なるシステムに勝手気ままに存在し、システムをセットアップしたときに入っていたバイナリをそのまま使い続けている
macOS もあれば複数の Linux 系もあり、FreeBSD のマシンもあって、さらにさかのぼれば Windows もあったと思う
それらの間を場当たり的に同期している
あるリポジトリは 10 年以上前のもので、1 つはコミットが 1 万件を超え、別の 1 つは開発環境全体をチェックインしているので数 GB ある
ときどき再ビルドが必要だと言われたが、そのたびに成功してきた
コミット中にタイプミスを見つけると、癖で
ctrl-cで中断することもあるそれでも一度もがっかりさせられたことはない
Fossil は、私が使ったことのあるプログラムの中で圧倒的に 最も信頼性の高いプログラム だ
Fossil の基盤アーティファクト形式は最初から現在まで互換性がある
改善はあったが破壊的変更はなく、多数の Fossil Forum ユーザーの間でもそのような破損報告はなかった
推測するに、新しい Fossil の拡張機能を使って何かをチェックインしたあと、その新機能を理解できない古い Fossil で取り出そうとしてエラーになった可能性が高い
たとえば Fossil は当初 SHA1 ハッシュしか使っていなかったが、SHAttered 攻撃のあとで SHA1 と SHA3 の両方をサポートするように強化された
もちろん推測だが、それが最もありそうに見える
私は SQLite リポジトリ、Fossil 自身のホスティングリポジトリ、手元にある 100 個以上の Fossil リポジトリについて、純粋なバックアップを一度も作ったことがない
災害対策として別マシンにクローンは作ってある
実際、世界中の複数のマシンで cron ジョブが SQLite のような重要な Fossil リポジトリを 1 時間ごとに
syncするよう動いているしかし純粋なバックアップは一度も作っていない
数年前、メインの SQLite リポジトリが一度だけ壊れたことはある
何らかの事情でファイルディスクリプタ 2 が閉じられ、リポジトリである SQLite データベースを開く際にそれがファイルディスクリプタ 2 で開かれた
その後、Fossil のあるバグによって
assert()が発生し、ファイルディスクリプタ 2 に書き込んでデータベースの一部を上書きしてしまったクローンからリポジトリを復旧し、Fossil の assertion の欠陥を修正し、SQLite が 3 未満のファイルディスクリプタを使わないよう強化した
あわせて読むとよい資料: https://fossil-scm.org/home/doc/trunk/www/selfcheck.wiki
SQLite 開発者の 信頼性へのアプローチ を考えると、修正されるべき致命的バグと見なすべきに思える
ただし通常は復旧不能ではなかった
うわ、これのせいでかなり深掘りしてしまった
ここしばらくで見たものの中では、おそらく最高だった
Fossil を使いながら Git/GitHub へミラーリングすることもできそうだ: https://fossil-scm.org/home/doc/trunk/www/inout.wiki
内蔵 UI は良さそうで、実用的だし探索もしやすい
ただ、UI からコミットもできればと思ったが見つけられなかった
そうなれば、作業を完了するためにコマンドラインと Web インターフェースを混ぜて使わずに済む
Fossil の上に
open,init,commit,sync,sync-with-git,start-web-interfaceをサポートする ラッパー UI を作れれば、あるいは Fossil 自体に組み込めれば、あまり技術的でない人や開発者ではないがコードを扱う人、たとえば生物学・数学・データサイエンス分野の人たちが Jupyter notebook などを管理するのにかなり役立つと思うもちろん単純な git UI クライアントでもそうした用途には使えるだろうが、その場合は内蔵 wiki とチケットを失うことになる
ローカルで作業できる能力も有用だが、それは git でも可能だ
いずれにせよ、あまり技術的でない人たちが git、あるいはバージョン管理全般を敬遠するのを見たことがある
同じリポジトリに 内蔵 wiki とチケット が入っていることには可能性を感じる
バックアップすべきファイルが 1 つだけという点も興味深い
ソフトウェア開発者にとって バージョン管理システム は IDE や基盤となる OS と同じような道具だと思う
こうした道具はいじる時間が少ないほど生産的だ
複数のバージョン管理システムを使ってきた立場からすると、Fossil は自分にとって完璧な sweet spot にある
文字どおり、設定しておけばあとは忘れていられる