20周年記念にGitを嫌いになろう
「Gitは最悪のバージョン管理システムである、ほかに使われたバージョン管理システムを除いては。」というのはチャーチルの言ってない名言です。
バージョン管理から逃れることはできません、逃げた先には約束された破滅が待っているのですから。
バージョン管理システムは、誰が何をどう変更したのかを記録し、誰かがやらかしたときに巻き戻し、誰かと開発を分割可能にするために存在します。
そしてそれに使われるのは、だいたいGitです。(たまにSVNもあるけど)
GitはLinuxカーネルの開発のためにリーナス・トーバルズ氏が作った分散型のソフトです。
初版が出たのは2005年の12月21日、そろそろ20年が経ちます。
さて、ソフトウェア開発界隈はそんな古いツールをいつまで使い続けるつもりなんでしょうか?
あんなにも新しいモノ好きなのに?
例えばテキストエディタの流行はどんどん移り変わっています。
VimだEmacsだと言っていたかと思えばVisual Studio Codeが主流になっている。
そしてCursorやらKiroやらAI駆動開発に向いているとされるエディタが湧いている状態です。
Visual Studio Codeのリリースは10年前です。
なのにバージョン管理システムは20年モノを使っている。
それってなんかおかしくないですか?
さて、この記事の目的は「Gitを嫌いになること」です。
そして、自分なりのバージョン管理システムを提案して、最後はGitに敗北します。
Gitの問題たち
1. 増え続ける枝
ブランチが作りやすいことはGitが評価される理由の1つです。
Gitのブランチは、コミットにくっついたただの印です。
たった41バイトのデータが増えるだけなのでいくらでも増やせます。
参考資料: Git - ブランチとは
ブランチが雑に作れるので、他の人の作業に気を付けなくて良くなります。
自分専用のブランチを作ってしまえば、他の誰かが邪魔してくることも、誰かに迷惑をかけることもなくせます。
いくらでも増やせるブランチ、しかしそれは同時にGitの弱点でもあります。
増えれば増えるほど、ブランチとブランチの関係が分かりにくくなり、見通しが悪くなってしまうのです。
メインブランチとそこから生えた無数のブランチ、そしてユーザー毎に生成されるローカルブランチ。
それぞれの進捗状態は不明確で、そこには同期されていないコミットも、コミットされていない変更の存在もありえます。
これはまるで剪定されていない庭木のようなものです。
不細工に枝が飛び出ていて、よく見ると一部が枯れていて、安易に近づいたら毛虫が降ってくる木です。
こんなものの全体構造は簡単に理解できるわけがありません。
しかも悲しいことにブランチをどう管理しても開発中のシステムの機能とは本質的に無関係です。
(コンウェイの法則は黙っててください)
管理されないブランチは、ただ事態を無意味に複雑化して混沌を生むだけの厄介者です。
2. 分散型という虚像
Gitは 分散型 のバージョン管理システムです。はい、そうですね。
分散システムということは、一部が生き残っていれば機能は維持されるという意味ですね?
つまり、インターネットがなくても社内LANが落ちても開発は滞りなく続けられますよね?
ん?だめ?じゃあ分散型である意味って何なんですか!?!?!?
GitHubでもGitLabでもセルフホストでもなんでもいいですが、実運用上はサーバーが無いと何もできません。
思想的には分散型だったかもしれませんが、実運用について言えばこれを中央集権型と言わずして何というのでしょうか?
3. 便利なのはGitではなくGitHubではないのか
冷静になってみてください、開発においてGitを単体で使ったことはありますか?
そこにはGitHubとかGitLabとかBitBucketとかのリポジトリマネージャーが常にいたはずです。
リポジトリマネージャーはこんなことをしてくれます
- ユーザーごとの権限設定
- ブランチ保護
- 開発ルールの管理
- プルリクエスト/マージリクエストによるレビューとコードの一元管理
- デプロイ自動化
- プロジェクト管理
どれも便利で必須級の機能ばかりです。
そしてどれもGit本体が提供する機能ではありません。(ユーザー情報保持とか認証とかはしてるにしても)
リポジトリマネージャーがめちゃくちゃに頑張っているだけではないですか。
もしかするとリポジトリマネージャーがたまたまGitを採用していたというだけで、Gitでなければならない理由なんてどこにも無いのではないでしょうか?
4. 高すぎる学習コスト
Gitは難しい。
雑多に作れてしまうブランチを把握できずに振り落とされ、分散型という虚言に踊らされ、リポジトリマネージャーの使い方に悩まされます。
しかも、それらを操作するときはターミナルコマンドだったりテキストエディタの拡張機能だったりWebページだったりバラバラ。
本質的に同じ操作だったとして、インターフェースによって違って見えるのはあまりにも初心者向けではなさすぎます。
加えて開発によってハウスルールが追加されていたりするともう大変。
Gitのルールなのかリポジトリマネージャーのルールなのか、分かりにくすぎます。
いったい何の恨みがあってこんな事するんですか!?
私はただソフトウェア開発がしたいだけなのに!!!
Gitは本来Linuxカーネルの開発のために突貫工事で作られたツールであり、リポジトリマネージャーで一般に用いられる一方で持ち前の複雑さをまるで隠しもせず、無造作に生える枝で際限のない状態を表現し、初心者から玄人まで等しく開発者を苦しめ続けるにもかかわらず、残念ながら開発にほぼ必須で救世主のように扱われているのです。
ふぅ...水をください。
ところでGitの語源は、間抜けとかノロマとかいう意味のスラングです。そんなツールを使っている人も同類かもしれません。
さてここからは、その間抜けでノロマな人間の1人として、Gitの代替ツールを考えて行きましょう。
ChatGPTとひたすら相談して考えました。
代替ツールのコンセプト
1. ブランチを捨て、3つの状態で管理
このツールは、ブランチによる管理を放棄します。
その代わりに更新を、① Ledger (本流), ② Draft (下書き), ③ Proposal (提案)の3つの状態で管理します。
Git / GitHubの用語で説明するなら、以下のようなイメージです。
- Ledger:mainブランチ
- Draft:featureブランチ
- Proposal:プルリクエスト、レビュー、レビュー対応
更新はファイルを変更から始まります。同時にDraftが作成されます。
Draftの作成が進んで初版が完成したら、Proposalとしてレビュー状態にします。
Proposalが承認されれば正式に更新がLedgerに組み込まれ、一連の作業が完了します。
この流れは不変で逆流しません。
その管理はGitHub Flowじゃん、リポジトリマネージャによる管理と同じじゃん、と思われるかもしれません。(私もそう思います。)
しかし重要なことは、今までサーバー側のリポジトリマネージャーだけで守っていたコードベースを、クライアント側も守るようにすることです。
例えば、mainブランチに対する直接コミット禁止ルールや、プルリク + マージ的な管理がまさにそうです。
リポジトリ全体で、悪意やうっかりミスによる破壊をツール側が絶対に許容しません。
2. リポジトリは常に同期
PCのLANケーブルを抜くとか機内モードにするとか意図的にオフライン環境を作らない限り、あらゆる更新は自動同期されます。
どんなに小さなコミットでもサーバーと全てのクライアントで同期します。
Proposalの承認に伴うLedgerの更新も同様です。
Ledgerに更新があれば、未承認のDraftとProposalにその更新は組み込まれます。
Gitで言うところのリベース操作が自動実行されることで、コンフリクトを早期解決する必要が生まれ、結果的にリポジトリが健全になるはずです。
※リベース:別のブランチの更新を取り込むこと
こうすることで、「環境によって見えているものが違う」という厄介な状況を回避できます。
3. 更新規模はポリシーで制限
人間が成果物をそれなりの品質でレビューできる量には限界があります。
DraftとProposalで可能な更新ステップ数や変更ファイル数は、リポジトリのルールで制限できるようにします。
もし大量の更新が必要ならば、このツールはDraftとProposalを細分化することを推奨します。
そのための更新差分の分割機能の搭載が必要になります。
ポリシーにはほかにも、Proposalの承認期限なども設定できるとよさそうです。
腐敗する前に、更新なんて無かったことにしましょう。
命名
いい加減「代替ツール」とか「このツール」とかいうのは分かりにくいので、Arxtrus(アークトゥルス)と呼ぶことにします。
被りを防ぐために綴りを変えましたが元ネタは星の名前です。
深い理由は特にないです。
※ChatGPTが最初「Arxid(ない単語)」を提案してきて、そこから連想した名前にしました
ArxtrusとGitの比較
ArxtrusがGitの弱点を補えているかを考えてみます。
1.増えない枝
Gitは手軽に枝を増やすことができます。
そのおかげで気軽に変更を試す自由が与えられます。
しかし、自由は無責任を生みます。
ブランチ同士の関係性、ブランチの状態の見通しはかなり悪く、中身を見ないと把握することはできません。
Arxtrusは枝が増えない、というか枝を捨てました。
分岐はすべて一時的なもので、必ずLedger (Gitで言うメインブランチ)に収束することが生まれた瞬間から確定しています。
試作はDraft、レビュー中はProposalという2つの状態に分け、中身を見なくとも大まかな状態は分かります。
ProposalはLedgerに統合されれば削除されるので、増え続けるということはありません。
2. 責任ある中央集権体制
Gitは、分散型をうたっていますが、それは「オフラインでも作業ができる」程度の意味でしかありません。
絶対に中央のサーバーが必須であり、多くの開発においてはオンラインであることが大前提になります。
Arxtrusは幻想としての分散型を捨てます。
中央のサーバーが責任をもって更新を管理し、クライアントの連携を保証します。
3. リポジトリマネージャーとの作業分担
Gitは、単体では使えません。
GitHubやGitLabといったリポジトリマネージャーがなくては開発になりません。
しかし、ArxtrusはGitでリポジトリマネージャーがやっていた機能の一部をツールの中に組み込みます。
主に、GitHub-Flow的なプルリク/マージと、リポジトリのポリシーが対象になります。
リポジトリマネージャーはCI/CDによる作業効率化や進捗管理など、より重要度の高い機能に専念できるようになります、最悪リポジトリマネージャーがなくとも最低限のリポジトリ管理ができます。
4. (たぶん)低い学習コスト
開発前なので何もわかりませんが、ArxtrusはGitより簡単です。
複雑なブランチ操作がなく、リベースなどのコマンドもいらないので覚えるコマンドは少なくて済みます。
初心者向けには、リポジトリをクローンして変更を開始すればOKなのでお手軽です。
一方で、経験者向けには、Gitの用語で対応関係を説明すれば伝わるでしょう。
問題があるとすれば、Gitより機能の制約が大きいのでストレスになる点です。
mainブランチとdevelopブランチで二層管理をするとか、複数バージョンを同じリポジトリで管理するとかはできない仕様になっています。
余談:複数ブランチ管理の欲求に対する反論
①mainブランチとdevelopブランチでの管理がしたい →Ledgerの更新に、タグをつける
Git管理下でも、developブランチ不要論はあります。
developブランチでの管理はタグをつけてリリースするという形で不要にできます。
タグ付けデプロイの思想的裏付け #Docker - Qiita
Arxtrusについてもこれを採用します。
Ledgerの更新にタグをつけて、製品リリースとして記録する仕様にします。
②複数バージョンを1つのブランチで管理したい →リポジトリを複製して分離する
リポジトリを分けて、過去バージョンと最新バージョンの管理は完全に切り分けます。
両方のブランチで同じ更新を必要とする場合があるかもしれないので、Arxtrusの場合はリポジトリ間連携を強める機能が必要になりそうです。(めんどくさそう)
Gitをどう置き換えるか
残念ながら、Gitはバージョン管理ツールの覇権を握っています。
SVNとかFossilとかMercurialとかPlastic SCMとか、Git以外にもバージョン管理ツールはあるんですが、Gitに勝ちそうな気配はまるで感じられません。
その理由の1つは、便利なリポジトリマネージャーのベースとしてGitが選ばれているからです。
Gitの代替ツールがGitより優れていたとしても、GitHubが使えなくては選択肢として排除されるでしょう。
Arxtrusはこの問題を、Gitとのプロトコル互換性を持たせることで回避します。
例えば、リポジトリをローカルではArxtrusで管理しつつ、リモートではGitHubで閲覧できるようすればよいのです。
ここまでの説明で伝わっているといいのですが、Arxtrusの機能はGitに強い制約を加えることで実現可能です。
内部でGitのコマンドを呼び出してやればArxtrusの機能が実現できます。たぶん。
(まだ構想段階なので厳密な議論はご容赦ください。)
Gitからノーリスクで乗り換える道があれば、Gitより使い勝手のいいツールに切り替えたくなる人は少なくないはずです。
一部でも置き換えることができれば、あとはじっくりと徐々にGitを乗っ取るだけです。いやいやいやいや....
Gitへの敗北宣言
残念ながら、ArxtrusがGitに勝つことは無いでしょう。Gitはきっとこれからも使われ続けます。
混沌と複雑さを内包しているのに、Gitはなぜバージョン管理ツールとして選ばれ続けるのでしょうか?
もちろん1つには、Linuxカーネルの開発という揺るぎない実績はあるでしょう。
あとはGitHubやGitLabの基幹ツールとして採用されたこともそうですね。
しかし純粋な機能だけに注目するならばどうでしょうか?
私はGitの粗雑と軽薄さこそがむしろ選ばれる理由かもしれません。
Gitは管理に神経を使いますが、一方でどんな開発のやり方も阻害しないだけの汎用性があります。
ウォーターフォールモデルだとかアジャイルだとかDevOpsだとか開発手法には色々あります、大小のチームで開発することも、個人で開発することだってあります。
Gitは大したことはしません。だからこそ誰のことも邪魔しないのです。
そして、Gitが何もしないのをいいことに、周りが頑張るのです。
Gitを支える仕組みは変わり続けるでしょう。例えばGitHubCopilotのようなアシスタント機能が付いたように。
しかし核となるGitは柔軟にしぶとく生き残り続けるでしょう。何と言ってもLinuxの「核(カーネル)」のために作られたのですから。
Arxtrusはどうでしょうか?堅牢さを目指して、ルールの殻に閉じこもります。
予想もしない時代の変化にはついていけないでしょう。
さいごに
最初にも書きましたが、2025年でGitは20周年を迎えます。
日本なら飲酒が可能になる歳です。もっと酔いどれの間抜けとして開発者をより一層の地獄へといざなってくれるでしょう。
私はデファクトスタンダードが嫌いです。
なので、試しにGitを嫌ってみることにしたのです。
私の現在の理想は、「人間の意志を必要としないこと」です。
完璧さを追求するために不断の努力を強固な意志で継続する世界ではありません。
人が自然にふるまえばすべてがうまくいく。そんな構造を作り上げるべきなのです。
Arxtrusはその思想と不可分で、現在の私のスナップショットとしての一人の間抜けなりのアイデアをまとめてみました。
皆さんはバージョン管理に何を求めますか?
謝辞
本記事の執筆にあたり、GitおよびGitHubを使用しました。
Discussion
masterに直push開発しか置き換えられなそうに見えます。
branchを複数作れる機能は必須だと思います
Ledgerブランチが複数個存在するプロジェクトもあります
例えばゲーム開発においてはローカライズ言語ごとにLedgerブランチがあることがあります
事実として少なくない数のゲームで言語ごとに実行ファイルのハッシュが別になっています
専門家ではないので素人意見ですが,ホスト側(例:GitHub)がリッチなら,クライアント側(例:VSCode)もリッチにする考え方と理解しました.その一つとして,Arxtrusは理解できますが,一方で,Gitの機能をより使いやすくするように進化するのはありかと考えます.例えば,git subtreeは便利ですが,現状のIDE上の操作・表示だと理解困難で,より分かりやすい可視化や管理方法への対応はあるかもしれません.
正味,Githubは多機能で使いやすい一方で,クライアント側は使いにくいです.(クライアント側に多くの機能や利便性が求められていない懸念はありますが.)
Gitを複雑と感じたことがなく、便利すぎて重宝してます。
学習コストも高いと感じたことがないです。
運用の仕方によっては最悪の手間ばかりかかることはありますが運用設計次第だと思います。
git の代替には興味があります。
jujutsu なんかも筋は悪くないと思いますが、バックエンドは git なんですよね。
あとは Unison みたいな一体型という道とか…
gitが優れている点のひとつに、git自体が特定の方法論を強制しないことがあります。
例えば私は、社内にしぶとく残るSVNのプロキシとしてもgitを使っています。諸々の管理不足で中央リポジトリは頻繁に不安定になりますが、分散リポジトリを間に挟むことでインフラの問題と作業を切り離すことができています。
あなたが今gitに感じている不満は、実際にはGitHubがgitの複雑さを十分に隠蔽できていないことに起因しているのではないでしょうか?その解消には、gitを別のものに置き換えるのではなく、ご自身の開発規模と環境に最適化された「リポジトリマネージャ」を作る方向に向かうべきなのかなと思いました。