──「心をgitで管理する世界」の物語で、forgeという檻の話をする
〈ショートストーリー〉
ふだん、それは環境音だった。
私の心のリポジトリが、どこかのサーバーにホストされている、ということ。forge、と呼ばれていた。電気や水道と同じで、あることすら忘れていられた。私がcommitし、checkoutし、たまに誰かとfetchし合う ── その全部の下に、静かに敷かれた、床。
その床が、ある日から喋りはじめた。
最初は、通知だった。
〈新しいissueが立てられました〉
母が、私のリポジトリにissueを立てていた。
孫はまだですか #1
⊙ Open · 母 opened this issue · 0 comments
────────────────────────────────────────
Assignees あなた
Labels priority:high
開くと、本文は一行だった。「元気にしてる? 母より」。
priority:high を付けたのは、たぶん、母じゃない。forgeが、母の言葉をそういう様式に勝手に整えたのだ。心配を、チケットに。
私は、closeしようとして、やめた。closeすれば、母に「対応済み」の通知が飛ぶ。愛から立てられたissueを、事務的に閉じる ── それはできなかった。かといって、放っておけばダッシュボードの隅で未対応の「1」が赤く灯りつづける。
翌週、親戚がissueを足した。
Open 3
────────────────────────────────────────
⊙ そろそろ定職に #2 親戚 opened
⊙ 親御さんを大事にね #3 親戚 opened
⊙ ↑ の件、その後どうですか #4 親戚 opened · referenced #2
赤い数字が増えていく。どれも悪意はない。むしろ逆だ。みんな、私のことを本気で心配している。愛から発行されたissueは、却下できない。却下する理由が、どこにも無いからだ。
──
会社では、上司がPull Requestを開いた。
あるべき社会人像へ #7
Open · 上司 wants to merge 1 commit into あなた:main from template:ideal-employee
+218 −196
diffを開くと、それは私を書き換える変更だった。口数の多い行を削る。出すぎた意見を丸める。私の枝をどこかにある「理想の社員」のテンプレートに近づけていく。
「approveするかどうかは、もちろん、君の自由だよ」と、上司は言った。「君のリポジトリ、なんだからね」
いい人だった。本気で、私のためだと、思っていた。
ただ ── CIは緑だった。レビュー承認もすでに揃っていた。チームの全員が、そのPRに目を通していた。「LGTM」「いいと思います」。親指の絵文字が並んでいた。
全員が、良かれと思って出したPRを一人だけdeclineする。そのボタンを押す勇気は、私にはなかった。自治はちゃんと保障されていた。誰も強制はしていなかった。ただ、断れない構造だけが、完璧に整っていた。
そして、私はいつのまにかグラフを見るようになっていた。
一年ぶんの、小さなマス目。commitした日は緑に灯る。しない日は灰色のまま。連続記録が途切れないように、私はcommitを打ちはじめた。
見られるための、commitを。
意味のない更新でもいい。とにかくマスを緑に。誰かが私のプロフィールを見たとき、よく活動している人間に、見えるように。starの数を気にするようになった。フォロワーが一人増えると、その日が少しだけよく思えた。
ある夜、私は何でもない一行をcommitしようとして ── ふと、手が止まった。
昔、私はこういう一行を、自分のためにcommitしていた。「今日、空がきれいだった」。誰にも見せない私だけの履歴に。
今は違った。commitする前に、考えている。これはグラフに緑を点けるだろうか、と。
そのとき、初めて、思い出した。
issueも、PRも、緑のグラフも、starも ── あれは全部、forgeの機能だ。gitのものじゃない。
gitは、ずっと私だけのものだった。私的で、分散していて、誰にも測られない、記憶。私が一人でcommitし、誰と fetchし合うかを、私が決める。そこには、未対応の赤い数字も、承認待ちのPRも、緑のマス目も、無かった。
それをぜんぶ後から床の上にforgeが敷いた。
forgeの売り文句を思い出す。「あなたのリポジトリはあなたのものです。あなたがmaintainerです」。
完全な自治の約束。
なのに、issueは私の予定を埋め、PRは私の中身を書き換え、グラフは私の一日を採点する。maintainerは、私のはずだった。決めるのは私のはずだった。
PR #7の画面に戻る。
「Approve」と「Request changes」。二つのボタン。
approveすれば、私のmainは、角の取れたテンプレートの社員に書き換わる。みんなが安心する。母のissueにも、たぶん近づく。
declineすれば、全員の善意を一人ではねつける。評判の緑が欠ける。愛する人たちを落胆させる。
どちらにも、正解はなかった。
私は、長いこと二つのボタンを見ていた。押せなかった。どちらも。
その夜、私は一つだけcommitした。
pushはしなかった。グラフには点かない。誰にも見えない。「今日、空がきれいだった」。昔と同じ一行を。
自由を取り戻したのか。それとも、forgeに明け渡した広い土地の、その隅に、かろうじて残った最後の私有地に、しがみついただけなのか。
たぶん、後者だ。
赤い「1」は、まだ灯っていた。PRは、まだ私の返事を待っていた。グラフの今日のマスは、灰色のままだった。
私は、その灰色をしばらく見ていた。
緑にしたい、と思っている自分がいた。
〈技術ノート〉── gitとforgeは、別の層だ
ノートは答え合わせではない。物語が嘘をついた、ちょうどその場所の地図である。
まず、層をはっきり分ける
- git ── 分散バージョン管理の 道具。commit・branch・clone・fetch・merge・rebase。すべてローカルで完結し、中央のサーバーを必要としない。あなたのrepoは、本当にあなたのもの。誰の許可もいらない。
-
forge ── そのgitを ホストする商業プラットフォーム(GitHub・GitLab等)。git の上に、後から乗せられた層。
そして、この章に出てきたものは、一つ残らず、forgeの機能であって、gitではない。
| 物語の言葉 | 正体 | git か forge か |
|---|---|---|
| 母・親戚のissue | issueトラッカー | forge(gitにissueは無い) |
| 上司の Pull Request | PR (GitLabだとMerge Request:MR) |
forge(gitにPRは無い。近いのは git request-pull だが、ただのメール用要約。承認もCIも無い) |
| CI 緑・LGTM・承認待ち | status checks / code review / required approvals | forge(ガバナンス機能) |
| 緑のマス目 | contribution graph | forge(forge へ push した活動の可視化。あなたの仕事や人生の量ではない) |
| star・フォロワー | ソーシャル指標 | forge |
| mainを勝手に守る掟 | branch protection / CODEOWNERS | forge |
gitだけなら、これらは一つも存在しない。ローカルでcommitし、git remote add で相手と直接つなぎ、パッチをメールで送り合う(git am)── forge無しで、gitは完全に回る。forgeは任意の足場にすぎないのに、いつのまにかそれが「当たり前の床」になった。
看板の嘘
「あなたのリポジトリはあなたのものです。あなたがmaintainerです」── この自治のレトリックは、git上では本当だ。ローカルのrepoは誰にも奪えない。どんな変更も、あなたは拒否できる。
forgeは、その「本当」を看板に掲げたまま、上に、自治を空洞化する構造を積む。
- issueは、却下しにくい義務を、あなたのダッシュボードに積む(しかも、愛から発行されると、closeボタンが押せない)。
- PRは、形式上「approveは君の自由」と言いながら、CI 緑・全員承認という社会的圧で、declineを高コストにする。名目の自治と実質の強制の落差。
- contribution graphは、「見られるための commit」を誘発し、私的だった記憶を採点されるパフォーマンスに変える。
-
branch protectionは、「main=正式なあなた」に、forge側のルール(必須レビュー・必須 CI)を課す。
最後の一点が効く。gitは、どのブランチにも特権を与えない(mainも一本の枝にすぎない)。「mainこそ正式な自分」という感覚は、gitのものではなく、forgeがbranch protectionで外から差し込んだ「本物」だ。
誰も、悪人ではない
これが、forgeを最も柔らかい檻にする。
母は、愛からissueを立てる。上司は、本気で「君のため」とPRを出す。チームは、善意で承認する。誰一人、あなたを支配しようとはしていない。だからこそ断れない。 悪意なら、はねつけられる。善意と計測がforgeの機能に乗ったとき、それは抵抗する角を失う。
そして、決着はつかない。approveすればテンプレートになり、declineすれば愛する者を落胆させ、評判を失う。gitは「拒否する自由」を保障するが、forgeは「拒否したあとの社会的代償」までは引き受けてくれない。