20周年記念にGitを嫌いになろう
20周年記念にGitを嫌いになろう
Gitは最悪のバージョン管理システムである、ほかに使われたバージョン管理システムを除いては。
というのはチャーチルの言ってない名言です。
バージョン管理から逃れることはできません、逃げた先には約束された破滅が待っています。
バージョン管理システムは、誰が何をどう変更したのかを記録し、誰かがやらかしたときに巻き戻し、誰かと開発を分割可能にするために存在します。
そしてそれに使われるのは、だいたいGitです。
GitはLinuxカーネルの開発のためにリーナス・トーバルズ氏が作りました。
初版が出たのは2005年の12月21日で、そろそろ20年が経ちます。
さて、ソフトウェア開発界隈はそんな古いツールをいつまで使い続けるつもりなんでしょうか?
みんな、あんなにも新しいモノ好きなのに?
例えばテキストエディタの流行には移り変わりがあります。
VimだEmacsだと言って戦争していたかと思えば、Visual Studio Codeが主流に。
そして今現在はCursorやらKiroやらAI駆動開発に向いているとされるエディタが湧いている状態です。
ちなみに、Visual Studio Codeのリリースは10年前[1]です。
なのにバージョン管理システムは20年モノを使っている。
それってなんかおかしくないですか?
さて、この記事の目的は「Gitを嫌いになること」です。
そして、自分なりのバージョン管理システムを提案して、最後はGitに敗北します。
Gitの問題たち
1. 増え続ける枝
ブランチが作りやすいことはGitが評価される理由の1つです。
Gitのブランチは、コミットにくっついたただの印です。
たった41バイトのデータが増えるだけなのでいくらでも増やせます。
ブランチが雑に作れるので、他の人の作業に気を付けなくて良くなります。
自分専用のブランチを作ってしまえば、他の誰かが邪魔してくることも、誰かに迷惑をかけることもありません。
いくらでも増やせるブランチ、しかしそれは同時にGitの問題点でもあります。
ブランチが増えれば増えるほど、ブランチとブランチの関係が分かりにくくなり、見通しが悪くなってしまうのです。
メインブランチとそこから生えた無数のブランチ、そしてユーザー毎に生成されるローカルブランチ。
それぞれの進捗状態は不明確で、そこには同期されていないコミットも、コミットされていない変更の存在もありえます。
これはまるで剪定されていない庭木のようなものです。
日常のすぐそばにあるのに不細工に枝が飛び出ていて、よく見ると一部が枯れており、安易に近づいたら毛虫が降ってくる木です。
こんなものの構造は簡単に理解できるわけがありません。
しかも悲しいことにブランチをどう管理しても開発中のシステムの機能とは無関係です。
(コンウェイの法則さんは黙っててください。うまく管理すれば品質には貢献するであろう事は分かってます。)
管理されないブランチは、ただ事態を無意味に複雑化して混沌を生むだけの厄介者です。
2. 分散型という虚像
Gitは 分散型 のバージョン管理システムです。はい、そうですね。
分散システムということは、一部さえ生き残っていれば機能は維持されるという意味ですね?
つまり、インターネットがなくても社内LANが落ちても開発は滞りなく続けられますよね?
ん?だめ?仕事にならないって?
じゃあ分散型である意味って何なんですか!?!?!?
GitHubでもGitLabでもセルフホストでもなんでもいいですが、実運用上はサーバーが無いと何もできません。
機能的・思想的には分散型だったかもしれませんが、これを中央集権型と言わずして何というのでしょうか?
Gitはウソつきです。
3. 便利なのはGitではなくGitHubではないのか
冷静になってみてください、開発においてGitを単体で使ったことはありますか?
そこにはGitHubとかGitLabとかBitBucketとかのリポジトリマネージャーが常にいたはずです。
リポジトリマネージャーはこんなことをしてくれます
- ユーザーごとの権限設定
- ブランチ保護
- 開発ルールの管理
- プルリクエスト/マージリクエストによるレビューとコードの一元管理
- デプロイ自動化
- プロジェクト管理
どれも便利で必須級の機能ばかりです。
そしてどれもGit本体が提供する機能ではありません。(ユーザー情報保持とか認証とかはしてるにしても、ね)
開発において頑張っているのはリポジトリマネージャーであって、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に統合されれば削除されるので、増え続けるということはありません。
ArxtrusにおけるDraftと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はきっとこれからも、混沌を持ったまま使われ続けます。技術や品質では太刀打ちできません。
理由には、Linuxカーネルの開発という揺るぎない実績や、GitHubやGitLabの基幹ツールとして採用されていることが挙げられます。
しかし純粋に機能だけに注目するならばどうでしょうか?
Gitの粗雑さと軽薄さからくる柔軟性こそがむしろ選ばれる理由かもしれません。
Gitは大したことはしません。だからこそ誰のことも邪魔しないのです。
ウォーターフォールだとかアジャイルだとか、個人開発や大規模開発にだって使えます。
そして、Gitが何もしないのをいいことに、ユーザーが頑張るのです。
GitHubCopilotのようなAIアシスタント機能が付いたように。Gitを支える仕組みは変わり続けるでしょう。
しかし核となるGitは柔軟にしぶとく生き残り続けるでしょう。何と言ってもLinuxの「核(カーネル)」のために作られたのですから。
Arxtrusはどうでしょうか?堅牢さを目指して、ルールの殻に自分を含めたすべてを封じ込めます。
予想もしない時代の変化にはついていけないかもしれません。
でも、試みてみるだけの価値は案外あるかもしれません。
さいごに
最初にも書きましたが、2025年でGitは20周年を迎えます。
日本なら飲酒が可能になる歳です。もっと酔いどれの間抜けとして、より一層の地獄へ開発者を誘ってくれるでしょう。
私はデファクトスタンダードが嫌いです。
なんとなく、でその地位に居座っているその様が。
だから、試しにGitを徹底的に嫌ってみることにしたのです。最後には敗北しましたが。
私の現在の理想は単純です。それは「人間の意志を必要としないこと」。
人が自然にふるまえばすべてがうまくいく。そんな構造を作り上げるべきだと思っています。
完璧さを追求するために、不断の努力を強固な意志で継続する世界ではありません。そんな事は不可能です。たった1人の「間抜け」がいるだけで破綻するのですから。
Arxtrusはその思想と不可分で、私の現在のスナップショットとして、1人の間抜けなりのアイデアをまとめてみました。
皆さんにとって考えのきっかけになれば幸いです。
さて、皆さんはバージョン管理システムに何を求めますか?
ここまで読んでいただきありがとうございました。
謝辞
本記事の執筆にあたり、GitおよびGitHubを使用しました。
似た方向性の過去記事(この時Zennやってなかった):
-
都合のいい事例のチェリーピッキングですね はい ↩︎
Discussion
masterに直push開発しか置き換えられなそうに見えます。
branchを複数作れる機能は必須だと思います
Ledgerブランチが複数個存在するプロジェクトもあります
例えばゲーム開発においてはローカライズ言語ごとにLedgerブランチがあることがあります
事実として少なくない数のゲームで言語ごとに実行ファイルのハッシュが別になっています
専門家ではないので素人意見ですが,ホスト側(例:GitHub)がリッチなら,クライアント側(例:VSCode)もリッチにする考え方と理解しました.その一つとして,Arxtrusは理解できますが,一方で,Gitの機能をより使いやすくするように進化するのはありかと考えます.例えば,git subtreeは便利ですが,現状のIDE上の操作・表示だと理解困難で,より分かりやすい可視化や管理方法への対応はあるかもしれません.
正味,Githubは多機能で使いやすい一方で,クライアント側は使いにくいです.(クライアント側に多くの機能や利便性が求められていない懸念はありますが.)
Gitを複雑と感じたことがなく、便利すぎて重宝してます。
学習コストも高いと感じたことがないです。
運用の仕方によっては最悪の手間ばかりかかることはありますが運用設計次第だと思います。
git の代替には興味があります。
jujutsu なんかも筋は悪くないと思いますが、バックエンドは git なんですよね。
あとは Unison みたいな一体型という道とか…
今の使われ方的に中央集権じゃんってのいっつも思う。
git の入門ページとかに分散型っていうのが利点としてよく挙げられるけど、今その説明必要なのか疑問。
Vusual Studio自体30年前からあるでしょ。
30年前 バージョン1.0を 秋葉原で買いに行った記憶がある。
FD 20枚組。
Gitって一人ぼっちでも使い方を覚えられますかね?
同じような思想はPerforceなどでも採用されてますが(p4 streamなど)、LTS対応や複数製品展開を伴うプロジェクトではリリース時にブランチを分けてcherry-pickで変更を適用する方が現実的で、一本化やリポジトリクローンの運用は、実際にやってみるとコストやら開発体験やらデバイス容量やらで非常にきついことがわかります。
あと分散型の真の利点はオフライン作業が可能な点で、ローカルでブランチを切り替えて複数の作業を並行できる柔軟性にあるのかなぁと思います。中央集権型ではどうしても同期が強制されるので、緊急作業の割り込みや作業の同時並行に弱いです。
とはいえ思考実験としては中々面白く、かなり緻密に考えられているアイデアだなぁと感じましたし、Githubありきな機能が多い所など、一歩引いた視点による考察ならではの考えさせられる点もあるなと思いました(上から目線みたいなコメントでスミマセン)
内容以上に文章がなんかおもろくて読まされる記事でした。
とは言えgitは保守的すぎる気はする。
gitの基本的な考え方を壊さずにもっと便利する方法(revsetとかundoとかルートコミットとか)はあると思うけれど、頑なに変化させようとしない。
コマンドのラッパーにすぎないrestoreとswitchすら導入するのに十年以上を必要としたので……。
あ、それとgitをもっと良くした物を作ろうとするプロジェクトは結構いろいろあるみたいですね。