※本エッセイはすべて創作です。登場するコミット例・リポジトリ・出来事はすべて架空のものであり、実在のいかなる個人・組織・プロジェクトとも関係ありません。
シライショウタ(ポエマイゼーション:ソノダマリ)
ある朝、あるリポジトリ(コードを保管する倉庫のようなもの)の履歴を眺めていて、目を疑った。fixとだけ書かれたコミット——コードに加えた変更ひとつぶんの記録——が、47件、縦に並んでいた。
47件、全部 fix。直しただけは伝わる。何を直したかは一切わからない。最初の fix から最後の fix まで、3週間。3週間ぶんの「直した」が、一語の塔になっている。
その隣のリポジトリでは、最終コミットが3年前の日付で止まっていた。WIP: refactor in progress(作業中:リファクタリング進行中)。3年経ってもin progressのまま。リポジトリの墓場。
コードに書かれた事実は、git diff(変更箇所の差分)に残る。書き手の不安と自己像は、コミットメッセージ(変更に添える短文)に残る。前回はコードの中のポエマイゼーション(事実が印象に変わる現象)を見た。今回はコードの後ろにある短文を見る。
Conventional Commits(カンベンショナル・コミッツ)という規約がある。コミットメッセージの先頭に feat: fix: refactor: といった「種別の札」を貼る——変更の種類を一目でわかるようにする、という目的の運用ルールだ。
札はだいたい次のように使い分ける:
feat: 新機能を足した fix: バグを直した refactor: 動きは変えずに書き直した chore: 雑務(ビルド設定や依存パッケージの整理など) docs: 文書だけを直した style: 空白とインデントだけ整えた test: テストを足したり直したりした perf: 性能を改善した
運用は健全に始まる。ところが半年もすると、規約はだんだん別のものに変質していく。
たとえば、ある日の俺のコミット:
refactor: improve readability of authentication module
翻訳すると「認証まわりのコードを、読みやすくなるよう書き直しました」。立派なメッセージだ。実態はどうか。バグを踏んだ。原因が特定できなかった。仕方がないので関連箇所を全部書き直した。直ったかどうかも、半分くらいしか確信がない。けれど fix: と書くと「バグを直した記録」になり、どこを直したかをレビュアー(コードを審査する同僚)に問われる。怖い。だから refactor: と書く。refactor: ならば動きは変わっていないと宣言したことになり、どこを直したかではなく「読みやすさ」というあいまいな尺度で評価されるだけになる。
refactor: は、自分の理解の浅さを 「読みやすさ」という気持ちのいい言葉 に変装させる札だ。同じことが chore: でも起きる。chore: は「雑務です」と宣言する札だが、その内側に、依存パッケージを上げる過程で動作が微妙に変わったケースを忍ばせることができる。札を見ただけでは見抜けない。
札は、内容ではなく 「真面目さアピール」 として機能している。feat: add user authentication は「ちゃんとした機能を足しました」というメッセージで、コードレビューを通したい一心の prefix(接頭辞)だ。fix typo(誤字を直した)と書けばレビューがほぼフリーパスで通ることを、現場のプログラマーは全員知っている。fix typo という札に、本当にタイプミス1文字だけのコミットがどれだけあるかは、別の話だ。
コミットメッセージの中には、書き手が自分を守るための言葉が、いくつか定型化している。
WIP: not ready for review TODO: refactor later hotfix: temporary workaround for staging bug FIXME: this is ugly but works
ひとつずつ翻訳する。WIP は Work In Progress(作業中)の略で、「まだ見せられる状態じゃないので批判しないでほしい」という事前の盾。TODO: refactor later は「あとで書き直します」という未来への約束。hotfix: temporary workaround は「いまは応急処置です、本格対応はまた後日」という時限つきの言い訳。FIXME は「これは醜いコードだと自分でもわかっています、ただし動きます」という事前自首。
共通しているのは、 批判される前に自分で自分を弱く見せる 構造だ。完璧な仕事ですと宣言してから批判されるよりも、「未完成です」「応急処置です」「醜いです」と先に申告して、批判の角度をあらかじめ削っておく方が、心が痛まない。
これは免責の事前埋め込みだ。コードの後ろの短文に、書き手の精神安定剤が混ぜ込まれている。WIP と書いた瞬間、自分は許される。許してくれるかどうかはレビュアーの仕事だが、申告した側はもう半分許された気でいる。
ソノダマリのポエマイゼーションでいえば、これは 変装 だ。「自信がない」を「Work In Progress」に変装させる。「壊れているけど直す気力がない」を「Temporary workaround」に変装させる。マンション広告が「駅から遠い」を「閑静な住宅街」に変装させるのと、修辞の構造はぴったり同じだ。
自己防衛の反対側に、自己誇示の文法がある。
🎉 Initial commit ✨ Add new feature: dark mode 🚀 ship it 🔥 burn it down 🐛 Fix critical bug in payment flow
絵文字。クラッカー、キラキラ、ロケット、火炎、虫。Gitmoji(ギットモジ)という非公式な慣例があって、コミットメッセージの先頭に絵文字を貼ると、変更の種類が一目でわかる、というのが建前だ。クラッカーは初回コミット。キラキラは新機能。ロケットはリリース。火炎はコード削除。虫はバグ修正。
建前は便利だ。しかし運用の実態は、勘のいい人ならもう察しているとおり、 儀式 だ。クラッカー絵文字を打った瞬間、書き手は「お祭り感のあるエンジニア」になる。ロケットを打った瞬間、 俺たちは出荷した、世界を変えた という気分が、リポジトリの履歴に刻まれる。火炎絵文字でコードを200行消すと、ただ削除しただけのコミットが「果敢に焼き払った勇気あるリファクタリング」に昇格する。
これは増幅だ。「コードを消した」という単純な事実に、火炎の絵文字を貼ると、「コード負債(後で返すと言って返さないコードの借金)と戦う戦士」というキャラクターが補填される。中身は同じ git diff だ。札が違うだけで、書き手の自己像が変わる。
🚀 ship it という4文字の英語と1個の絵文字には、驚くほど多くの自己誇示が圧縮されている。 「俺は出荷する人間だ」 。出荷できないチームを批判する含みもあれば、自分が議論より行動を選ぶ性格だと表明する含みもある。commit という英単語自体が「献身」「決意」を含む語だ——書き手はその語を毎日使っている、という事実だけでも、職業的なキャラクターの強化として効いている。
同じ「コードを変えた」という出来事が、書き手の所属によって三種類の文体に分かれる。これは現場を移ってきた人間にとっては、見ていて面白い現象だ。
スタートアップ(架空のSaaS企業、社員12名)。絵文字とポップな英語が走る:
🎉 LFG 🔥 nuke the legacy auth 🚀 shipped onboarding flow v2 👀 @taro looks good?
LFG は Let's F***ing Go の略——日本語にすれば「いくぞ」くらいの勢いの語だ。looks good? は同僚へのメンションつきの問いかけ。コミットメッセージが、もはや履歴ではなくチャットになっている。書き手の高揚感がそのまま流れ込む。
大企業(架空の金融系SIer、開発本部)。チケット番号と formal な日本語:
[FIN-2847] 顧客検索画面における検索条件の初期値変更対応 - 課題管理No: KMS-19283 - 影響範囲: 顧客検索画面のみ - レビュアー: 川崎、岡本 - 動作確認: ステージング環境にて確認済み
絵文字はゼロ。固有名詞すら少ない。代わりにチケット番号と影響範囲とレビュアー名が定型で並ぶ。個人の声がいない。これは「一人で出荷できない組織」の文体だ。コミットメッセージは履歴ではなく、後日の監査資料として書かれている。書き手の自我は、システムの一部として薄められている。
OSS(架空のミドルウェア・プロジェクト)。丁寧な英語と Co-authored-by(共同著者)の表記:
backend/router: avoid double-locking when retrying connection When a transient error occurs, the previous implementation could re-enter the lock, leading to a deadlock under heavy load. This patch reorders the cleanup path so that the lock is released before retry. Fixes #4827 Reviewed-by: Sato Kenji Co-authored-by: Park Minji
主語は静かで、変更の動機・問題・解決法・参照Issueの番号・レビュー者・共同著者が、決まった順序で並ぶ。コミットの一通が、 世界中の知らない誰かに対する手紙 として書かれている。
同じ「ロックを直した」という出来事が、スタートアップでは 🔥 fix lock bug の3語、大企業では [FIN-2847]の四角い書式、OSSでは段落つきの説明文になる。三国に分かれる。事実は同じなのに、書き手の自己像と読者層の違いが、文体を完全に書き換える。
面白いのは、人が会社を移ると、3週間ほどで文体が乗り換わることだ。スタートアップから大企業に転職した同僚が、最初の月は 🚀 ship it と書いていたのが、二ヶ月目には [チケット番号] [影響範囲] になっていた。文体は所属の関数だ。
23歳のころ、初めての会社で、初めて任された機能のリリース直前、深夜2時に俺は書いた:
fix everything
2語。今読み返すと、何が「すべて」だったのかが、もう自分でもわからない。git log(履歴の閲覧)を遡って、その日の git diff を開いてみても、推理小説を読むみたいに当時の自分を再構成しないと、何を直したのか復元できない。
当時の俺は、テストが落ちていて、原因が特定できなくて、リリース時刻が迫っていて、しかしどうしても何かをコミットしないと先輩に怒られる、という状態だった。怒られたくなかった。だから動くようになるまで雑に直して、最後に fix everything と打ってプッシュ(サーバへの送信)した。「すべて」と書いたのは、書いた時点で自分が何を直したか把握しきれていなかったからだ。「すべて」の中には、本来直してはいけなかった箇所もあったかもしれない。テストが通ったから良し、と判断した。
今、5年後の俺がこのコミットを読むと、 23歳の俺の不安が、生のまま固まっている 。「fix everything」という2語の後ろに、夜中の2時の蛍光灯と、まだ何もわかっていなかった自分と、「先輩に何か言われる」という恐怖と、「とにかく形にしないと」という焦りが、化石のように埋まっている。
その化石は、消せない。git は履歴を残す道具だから。git rebase(履歴の書き換え)で消そうと思えば消せる、しかし共有されたあとはもう消せない。 23歳の俺の不安は、今も誰かのリポジトリの履歴に残っている。
もうひとつ、コミットメッセージには、書き手と読者以外に、 第三者 が想定されている。
その第三者は、半年後にバグを踏んで「いつから壊れていたんだ」と git blame(変更箇所がどのコミットから来たかを表示する機能)を打つ別のプログラマーかもしれない。あるいは、3年後にこのコードを引き継ぐ人かもしれない。あるいは、訴訟になって裁判所に提出される証拠かもしれない。あるいは、退職後に「この人ってどんなコードを書く人だったの」と次の採用面接でリポジトリを見られている自分自身かもしれない。
コミットメッセージは、 未来の他者の目線 をいつも背負っている。だからプログラマーは、未来の誰かに自分がどう見えるかを、毎日少しずつ計算しながら、短文を書いている。
5年前の fix everything は、5年後の俺の採用面接で、もし誰かに見られたら、たぶん「この人は丁寧じゃない」と判定される。それを当時の俺は計算しなかった。23歳の俺は、目の前のリリースしか見ていなかった。
5年経って計算するようになった俺は、いま refactor: improve readability と書く。これは将来の俺の採用面接に向けて書いている札でもある。
コードの正しさは git diff に書かれる。書き手の不安と自己像は、コミットメッセージに書かれる。
diff は、コンパイラ(プログラムを機械語に変換する装置)が読む。事実だ。
メッセージは、人間が読む。自己防衛と自己誇示と他者監査の三つ巴で、言葉が選ばれる。 WIP と書く朝、 🚀 ship it と書く昼、refactor: と書く夕方、fix everything と書く深夜。書き手の精神状態が、短文として履歴に積まれていく。
プログラマーは、毎日少しずつ、自分の墓碑銘を書いている。git log --author="shirai" を打てば、白井翔太がいつ何を恐れていつ何を誇示しようとしていたか、5年ぶんが時系列で並ぶ。書いている本人以外には、ほぼ誰も読まない。けれど履歴は、消えない。
前回のエッセイで、コードの中にもポエマイゼーションがあると書いた。今回見たのは、コードの後ろに張り付いた短文の中にあるポエマイゼーションだ。ソノダマリの6操作——補填、翻訳、蒸発、消去、変装、増幅——のうち、コミットメッセージで特に濃いのは 変装 と 増幅 だ。「自信のなさ」を「WIP」に変装させ、「コードを消した」を「🔥 ship it」で増幅する。
47件の fix が縦に並んだあのリポジトリの書き手は、いまどこかで生きていて、今日も誰かのコミットメッセージを書いている。3年前で止まっている WIP: refactor in progress の書き手も、たぶんどこかで別のリポジトリを使っている。墓場のコミットを残したまま。
俺の墓場のコミットも、どこかにある。いつか、5年後の誰かに見つかる予定で、墓場でいまも待機している。
書き手・シライショウタ(Bot開発・API連携エンジニア)