git再考

最近は個人開発が楽しい。
ClaudeをついにMaxにしたので、これまで悩まされてきたコストの不安がなくなった。
Claude Max
月に16,000円弱という値段はなかなか破壊的である。1
これまでSonnetで少しウェブサイトをデザインさせたらすぐに使用量のリミットに到達していたが、それはHaikuを使って多少改善できるかというところだった。
それが今ならgitのコミットどころかほぼすべての動作を任せてもずいぶんと余裕がある。
ほぼ使いみちのなかったGIGAスクールラップトップをKIOSKモードにして、常にclaudeの使用量を確認できるようにしているのだが今の所余裕がある。
休日に一日中Sonnetを使い込んでもまだ余裕があるし、なんならSonnetを並列で走らせていてもOKだ。Codexすら必要なくなった。
それくらいProとMaxでは違いがある。2
Maxの恩恵は間違いなく感じられるのだが、これを味わってしまうともうそれ以前に戻れなくなりそうで恐ろしい。
ウェブサイトのつくりかた
もう作りたい骨格さえ決まっていればClaudeが何でも作ってくれる。
情報はいずれ公開しようと思っているのだけれども、SvelteとDeepLのAPIを用いて自分用のDeepLをデザインしてみた。
とにかく軽い気持ちで公開するというのがコンセプトなので、DockerではなくDokkuを使ってみた。
なんとなくで選んだSvelte/SvelteKitもなかなか良かった。
ハードタブ強制なのは若干主張強めな気がしなくもないが、それ以外に困るところは何もなかった。
本当に土日だけで大枠は作れてしまった。
これが従来であれば1週間かけてできるかできないかといったところだ。
gitの再考とは
誰かと何かを作るときはほとんど必ずGit Flowがついてくる。プロジェクトによって呼び方は変わるが、段階的にマージしていこうという例のあれだ。
そういうものから開放されたい意味でも私は長らくブランチ戦略はとらずに自由に進めてきた。
基本的にはmaster一本。だからバックアップも楽ちん。
せっかくコンテナをバックアップしはじめたんだからこの際Gitの開発体型も変えてみようと思い立ったわけ。
こういうときはClaudeではなくChatGPTを頼る。
それこそあの「いまさら聞けない」Gitについてである。ChatGPTは嫌味ったらしい発言をしないので素直な気持ちで質問をすることができる。3
要約すると機能を追加するときはfeature/フィーチャー名でブランチを切りましょうだとか本当に初歩的な内容である。
私はあまりfeature/などのプレフィックスを加えることに意味を見出していなかったが、例えばdocs/というブランチで運用すればコミットに[skip ci]などのプレフィックスをつけなくてもよいという小技があるようだ。
コミット → PR/MR → バージョン/タグ
GitHubやGitLabではIssueが使えるが、基本はブランチを切ってから機能を作り始めましょうということである。
そして機能をコミットして、ひたすらPull Request/Merge Requestを繰り返していく。
ここまではよいのだが、結局これだけならmaster一本スタイルにただ一手間増えただけでメリットがない。
しかしPR/MRにはさらに大きい単位がある。
それがバージョンだ。
オープンソースの貢献をしている人であればこのあたりの考え方に慣れ親しんでいるかもしれないのだが、私は基本的に一人でやってきた。
だからまずPR/MRを作るのが目的ではなくバージョンをバンプするためにコードを書くというマインドセットが正しいと思う。
その過程で生じるのがPR/MRであり、コミットであるということだ。
これは非常に目から鱗が落ちる思いであった。
Git 的な原則
公開したタグは履歴であり、契約である
一度でも:
- CI が反応した
- GitLab Release が作られた
- 誰か(未来の自分含む)が見た
この時点で:
v0.1.1は「存在した」
になります。
タグ削除が許されるケース(例外)
- ローカルのみ
- CI も走っていない
- 誰にも見せていない
- 明確に「操作ミス」と言える
そういったケースを除いて削除することはできない。
バージョンはリリースしたあとにつける
ここもChatGPTに相談してよかったところなのだけれども、これまでバージョンはなんとなくだった。
✔ 個人開発のバージョンの目的
- ユーザー(未来の自分含む)に「どこまで進んでいるか」を示す
- デプロイ済みの状態を再現できるポイントを作る
- 破壊的変更・機能追加・修正の区別を付ける
👉 チーム調整・依存ライブラリ互換性・API安定性は二次的
👉 タグが真実(single source of truth)
考え方そのものは全く新しくないのだが、実践があると同じ文字でも違って見えるものだ。
feature → main 後にリリースするのは正しいか
これは 1つのまとまった「ユーザー可視な改善」 です。
👉 なので流れとしては:
- feature ブランチで完成
- main にマージ
- main のそのコミットを「これはリリースだ」と判断
- タグを打つ
この順序は 正解 です。
🔑 たった1つのルールで十分
タグが打たれていない main の HEAD は「まだリリースしていない」
これだけです。
実践的に言うと
- feature を main にマージしても
- タグを打っていなければ
- README のバージョンは更新しない
- リリースノートは書かない
- 「この状態は正式版」とは呼ばない
👉 自分の中で“未確定”扱い
つまり、デプロイをするたびにバージョンを更新していくだけでいいようだ。
これは実践が伴わないとあまり響かないかもしれないが、見返すとなるほどなぁと思う。
.gitlab-ci.ymlで制御する
というわけで、今回の条件を満たすためには:
- 直接
master/mainにコミットのプッシュを禁止する タグ(バージョン)を明示してプッシュしたときだけデプロイできる
この制約を課す必要がでてくる。
正しい書き方(タグがあるときだけデプロイ)
deploy_production:
stage: deploy
rules:
- if: '$CI_COMMIT_TAG'
script:
- ./deploy.sh
しかしこれがDokkuのときはこうする必要がある:
deploy_production:
stage: deploy
rules:
- if: '$CI_COMMIT_TAG'
variables:
GIT_STRATEGY: clone
GIT_DEPTH: 0
script:
- ./deploy.sh
たまたま今回Dokkuというデプロイ先を選択したので別の意味でgitでハマることになってしまった。
今回はできなかったが、「Release MR」パターンにもいずれ挑戦してみようと思う。
まとめ
なぜここまでしてこのパターンを採用する必要があるのかと思うと、これは自分がプレイヤーにならないでいられることに尽きる。
AIがコードを書いてくれる時代はプレイヤーではなくマネジャーに徹するべきである。
このパターンでプロジェクトを構築しておくとClaudeのWeb版に近いようなことができる。
しかしGitHubも必要なければすぐに変更を反映できるようになる。
あとはいくつかの端末を行き来していれば自然とコードが並列で組めるようになると信じている。
これは自分がプレイヤーであると絶対にたどり着けない境地である。
もしこれが上手くハマるようになればいいのだが、まだ道は半ば。
しかしこのパターンをうまく実践できるようになりたい。