AIに大量に書かせたコード、いざ「戻したい」時に戻せますか? — コミットを“レビューとロールバックの単位”として設計する実践ガイド
はじめに:速くなったのは「書く」ところだけかもしれない
正直に言うと、最近こんな場面が増えてないですか。
AIに「この機能つけといて」と頼んだら、30分後には10ファイル・400行の差分が返ってくる。動かしてみたら、ちゃんと動く。「お、いけてるやん」と思ってマージする。
……で、その3日後。別の不具合が出て、「あ、あの変更が原因かも。一回戻したいな」と思った瞬間に、固まるわけです。
- どのコミットでその変更が入ったのか分からない
- 1つのコミットに、機能追加もリファクタもログ修正も全部混ざってる
- コミットメッセージが
updatefixwipばっかりで、何をしたのか思い出せない - 戻そうにも、欲しくない変更まで一緒に巻き込まれる
これ、わりとあるあるだと思うんです。
ここで気づいてほしいことが1つあって。AIで速くなったのは「コードを書く」ところだけなんですよね。「後から読む」「レビューする」「戻す」「原因を特定する」は、むしろ前より大変になってる。だって、人間が手で書いてた頃より、はるかに大量の変更が、はるかに速く積み上がっていくから。
そして、その「読む・戻す」の土台になっているのが、実は コミットとPR(プルリクエスト)の設計 なんです。地味ですよね。git の話なんて、もう知ってるよと思うかもしれません。でも、AIが大量にコードを吐く時代になって、いちばん効いてくるのが、この一番地味なところだったりします。
この記事では、コミットを「ただの保存」じゃなくて「レビューとロールバックの最小単位」として設計するという考え方を、用語の意味から、最初の一歩まで、できるだけやさしく整理していきます。gitは触れるけど「コミットの設計」なんて意識したことなかった、という人にこそ読んでほしい内容です。
この記事のコードや名前は、すべて説明用のダミー(
example-app/payment-serviceなど)です。特定のプロダクトや個人の情報は含みません。
まず、用語を全部かみ砕いておきましょう
「知ってるよ」という人は飛ばしてOKです。でも、ここを曖昧にしたまま進むと後半がフワッとするので、念のため。
- コミット(commit):変更の「セーブポイント」です。ゲームでいうセーブと同じで、「ここまでの状態」を名前(メッセージ)つきで記録する行為、またはその記録そのもの。
-
差分(diff):あるコミットで「どの行をどう変えたか」を表したもの。
-が消した行、+が足した行。レビューで人間が実際に目を通すのは、基本これです。 - PR(プルリクエスト / Pull Request):「この変更たち、本流に取り込んでもいいですか?」というレビュー依頼の単位。複数のコミットをまとめて、レビュー・議論・マージする場所。
-
git blame:あるファイルの各行が「どのコミットで・誰が・いつ」変更されたかを表示するコマンド。「この謎の1行、なんで入ってるん?」を追う時に使います。 -
git bisect:「いつからバグが入ったか」を二分探索で特定するコマンド。後で詳しくやります。犯人探しの強い味方。 -
git revert:あるコミットの変更を「打ち消す」新しいコミットを作るコマンド。履歴は消さずに、上から「なかったこと」を重ねるイメージ。 - atomic commit(アトミックなコミット):「1つのコミットには、1つの論理的な変更だけ」という考え方。これ以上分けたら意味が壊れる、という最小単位。
-
Conventional Commits:コミットメッセージに
feat:fix:みたいな「型」をつける書き方のルール。人間にも機械にも読みやすくなります。
このあたりが頭に入っていれば大丈夫です。では本題へ。
なぜ「AI時代」に、わざわざコミットの設計なのか
結論から言うと、AIは「大量で・混ざった」差分を出しがちだからです。そして、大量で混ざった差分は、後から読むのも戻すのも、人間にとってめちゃくちゃしんどい。
少し2026年の状況にも触れておきます。AI支援で書かれたPRは、人間だけで書いていた頃よりサイズが大きくなる傾向があると、いくつかの調査やベンダーレポートで報告されています(ある分析では平均で2割ほど大きい、という数字も出ています)。そして差分が大きいほど、レビューは雑になりやすい。人間って、数百行を超える差分が来ると、だいたい途中から「まあ大丈夫やろ」って斜め読みになるんですよね。正直に認めましょう、なります。
さらに、AIは1回の応答で「機能追加」も「ついでのリファクタ」も「ログの修正」も、ぜんぶ一気にやってしまうことがあります。これがいわゆる tangled commit(こんがらがったコミット) です。スーパーの袋に、食材も洗剤も電池も全部ごちゃ混ぜで突っ込んだ状態を想像してください。レジ(レビュー)で見るのも大変だし、「やっぱり洗剤だけ返品(revert)したい」と思っても、他のものまで引っかかって取り出せない。
ここで発想を変えます。
コミットとPRは、「保存」じゃなくて「レビューとロールバックの最小単位」だ。
つまり、「後から人間が安全に読めて、安全に戻せる、いちばん小さなかたまり」をどう設計するか、という話なんです。書くのはAIに任せていい。でも、どの単位で区切り、どんな意図を記録し、どうやって戻れるようにしておくかは、人間が設計する。ここがAI時代のエンジニアの腕の見せどころになってきます。
「AIにできるか」じゃなくて「人間が設計して保つべきか」。この記事はずっと、その線引きの話だと思って読んでください。
原則① atomic commit ― 1コミットに、1つの意味だけ
いちばん大事な原則がこれです。1コミット=1つの論理的な変更。
なぜatomicがそんなに効くのか。理由は3つあります。
- レビューしやすい:「これは入力バリデーションの追加だけ」と分かっていれば、レビュアーはその観点だけに集中できる。
-
戻しやすい:あとで「この変更だけ消したい」と思った時、
git revert <そのコミット>で、そこだけキレイに打ち消せる。 -
原因を追いやすい:
git bisectでバグ混入地点を二分探索する時、1コミットの意味が小さいほど「犯人」をピンポイントで特定できる。
逆に、tangledなコミット(機能追加+リファクタ+整形が全部入り)は、この3つ全部を壊します。
AIが出した「全部入り」を、人間が分ける
AIに「機能Aを足して」と頼んだら、ついでに無関係なファイルまで整形されて返ってきた、というのはよくあります。そこで使うのが git add -p(patchモード)。変更を「hunk(かたまり)」単位で選んで、コミットを分けるコマンドです。
# いま手元には「機能追加」と「無関係な整形」が混ざっている状態
# -p をつけると、変更のかたまりごとに「これをステージする?」と聞いてくる
git add -p
# 対話プロンプトでよく使うキー:
# y = このかたまりをステージする
# n = ステージしない
# s = もっと小さく分割する(split)
# q = やめる
# 「機能追加」に関係する hunk だけ y で選んでコミット
git commit -m "feat(cart): 在庫切れ商品をカート追加時に弾く"
# 残った「整形」だけを別コミットに
git add -p
git commit -m "style(cart): フォーマッタ差分を整理"
ポイントは、1回のAI生成を、1回のコミットにしなくていいということ。AIは大きく出してくる。それを人間が「意味のかたまり」に切り分ける。この切り分けこそ、レビューと巻き戻しのしやすさを決める設計判断なんです。
AIに「分け方」を相談するプロンプト
切り分け自体をAIに手伝ってもらうこともできます。ただし、最終判断は必ず人間。AIには「案」を出してもらう係に徹してもらいます。
あなたはコミット整理のレビュアーです。以下の git diff を読み、
「1コミット=1つの論理的変更」になるように分割案を出してください。
制約:
- 各コミット候補について、次を表で出す:
(a) Conventional Commits の型(feat/fix/refactor/docs/test/chore/style など)
(b) コミット件名の候補(50文字以内・命令形)
(c) このコミットに含めるべき変更のファイル名と行の範囲
(d) なぜ分けるべきかの理由
- 機能追加とリファクタが混ざっている場合は、必ず別コミットとして提案する
- 確信が持てない分割は「要・人間判断」と明記し、勝手に断定しない
- 破壊的変更(公開APIの変更・DBスキーマ変更など)が含まれる場合は警告する
--- diff ここから ---
{git diff の中身を貼る}
--- diff ここまで ---
これで返ってくるのは、あくまで「分け方の下書き」です。それを見て、実際に git add -p で手を動かすのは人間。AIは速く案を出すのが得意、人間は意味の境界を決めるのが得意。役割分担ですね。
原則② Conventional Commits ― 型をつけると、人にも機械にもやさしい
2つ目の原則は、コミットメッセージに型をつけること。Conventional Commits という、わりと広く使われているルールです。形はこれだけ。
<型>[任意のスコープ]: <要約>
[任意の本文]
[任意のフッター]
型は、たとえばこんな感じ。
| 型 | 意味 | 例 |
|---|---|---|
feat |
新機能 | feat(auth): パスワード再設定メールを追加 |
fix |
バグ修正 | fix(cart): 合計金額の丸め誤差を修正 |
refactor |
挙動を変えない内部整理 | refactor(api): 重複したバリデーションを共通化 |
docs |
ドキュメントのみ | docs(readme): セットアップ手順を更新 |
test |
テストの追加・修正 | test(cart): 在庫切れケースを追加 |
chore |
ビルド・雑務など | chore(deps): ライブラリを更新 |
なんで型をつけると嬉しいのか
「ただのラベルやん」と思うかもしれません。でも、この型には地味に大きな効果があります。
-
人間がスキャンしやすい:履歴を眺めた時、
featとfixが一目で区別できる。「最近、機能ばっかり足してテスト書いてへんやん」みたいなことに気づける。 -
機械が処理できる:型を見て、自動でCHANGELOG(変更履歴)を生成したり、バージョン番号を上げたりできる。
featならマイナー、fixならパッチ、BREAKING CHANGE:があればメジャー、というふうに SemVer(セマンティックバージョニング) と連動させられます。 - AIにとっても読みやすい:あとでAIに履歴を要約させる時や、リリースノートを書かせる時、型がついていると圧倒的に正確になります。
良い例と悪い例を並べてみましょう。
# ❌ あとで自分が泣くやつ
update
fix bug
いろいろ修正
wip
# ⭕ あとで自分が助かるやつ
feat(payment): Stripe Webhook の署名検証を追加
fix(payment): 金額を整数(最小通貨単位)で扱うよう修正
refactor(payment): 決済結果の判定を1関数に集約
下の3つ、パッと見ただけで「決済まわりを触ったんやな」「お金の計算をintにしたんやな」と分かりますよね。これが半年後の自分を救います。
コミットメッセージは「明日の自分への手紙」 ― 件名(What)より、本文(Why)
ここ、いちばん伝えたいところです。
コミットメッセージって、つい「何をしたか(What)」だけ書いて終わりがちなんです。でも、差分を見れば「何をしたか」は分かるんですよ。+ と - を読めばいい。
本当に後から欲しくなるのは、「なぜそうしたか(Why)」のほうなんです。
fix(auth): トークンの有効期限を24hから1hに短縮
本文(なぜ):
インシデント #1234 で、漏洩したトークンが長時間有効だったため
影響範囲が広がった。短縮で被害窓を狭める。
UX影響(再ログイン頻度の増加)は許容と判断(プロダクト合意済み)。
なぜ24hでなく1hか: 同等サービスの一般的な設定に合わせた暫定値。
リフレッシュトークン導入までのつなぎ。
半年後の自分(あるいは引き継いだ誰か)が「なんでここ1hなん?」と思った時、git blame でこのコミットにたどり着けば、答えがそこにある。差分には絶対に書かれていない「判断の背景」が残っている。これって、未来の自分への置き手紙そのものなんですよね。
AIに「Whyの下書き」を引き出してもらう
ここでAIの出番です。ただし注意。AIは差分から「What」は推測できるけど、「Why」はあなたの頭の中にしかない。だからAIには、Whyを「決めさせる」んじゃなくて、「言語化を手伝ってもらう」。
あなたはコミットメッセージの編集者です。
以下の git diff を読み、Conventional Commits 形式のメッセージ案を作ってください。
出力ルール:
- 1行目: <型>(<スコープ>): <50文字以内の要約・命令形>
- 空行のあと本文: 「この変更は何をしているか」を3行以内で
- 本文の最後に「### 確認してほしいWhy」として、
差分だけでは分からない “理由” の候補を質問形式で2〜3個挙げる
(例: 「この定数を30から10に下げたのは負荷対策ですか?」)
- 推測で理由を断定しないこと。理由は必ず人間に確認する形にする
--- diff ---
{git diff を貼る}
返ってきた「確認してほしいWhy」に、人間が一言ずつ答えて本文に足す。これで、AIが下書き、人間が意図を注入するという気持ちいい分担ができます。Whyを書くのは2分。でもその2分が、未来の誰かの数時間を救います。
AIの大きな差分を「レビューできる単位」に割る
コミットを整えたら、次はPRの単位です。原則はシンプルで、1つのPRには、1つの目的。
AIに任せると、つい「機能Aと、関連するリファクタと、ついでに型エラーの修正」を1つのPRに盛り込みがちです。でも、レビュアーの立場で考えてみてください。500行の混ざった差分が来たら、どこから見ます?……だいたい、見ないんですよ。LGTM(よさそう)を押して終わり。それ、レビューしてないのと同じです。
対策はいくつかあります。
- PRを小さく保つ:Googleのコードレビューガイドでも「小さな変更(Small CL)」が推奨されています。小さいほどレビューが速く、正確で、戻しやすい。
- PR stacking(スタック):大きな変更を「土台 → その上 → さらに上」と積み重ねた小さなPRの連なりにする。1枚ずつレビューできる。
- 目的が変わったら、PRを分ける:「リファクタPR」と「機能PR」は混ぜない。これだけでレビュー品質がガラッと変わります。
PR説明文も、AIに下書きしてもらう(根拠つきで)
PRの説明文(description)は、レビュアーが最初に読む「地図」です。ここが雑だと、レビューの質が落ちます。AIに下書きしてもらうと楽ですが、必ず「根拠(どのファイルのどの行か)」を添えさせるのがコツ。根拠を要求すると、AIの“それっぽい嘘”を見つけやすくなります。
あなたはPR説明文のドラフト作成者です。以下の差分から、レビュアー向けの説明文を書いてください。
必ず次の見出しで構成する:
## このPRの目的(1〜2文)
## 変更点(箇条書き・各項目に対象ファイル名:行 を根拠として添える)
## レビュアーに特に見てほしい点
## 確認手順(手元での動かし方・実行コマンド)
## ロールバック手順(問題が出た時に戻す方法)
## 影響範囲・リスク(不可逆な操作が含まれるか明記)
ルール:
- 差分から確認できないことは「要確認」と書き、推測で断定しない
- 根拠として挙げたファイル:行が実際に差分に存在するか、自分で照合してから書く
--- diff ---
{git diff を貼る}
「ロールバック手順」をPRに必ず書かせるの、地味におすすめです。「戻し方を最初に言語化しておく」と、戻すのが怖くなくなるんですよね。戻せる安心があるから、速く試せる。これ、後の章にもつながる話です。
「戻れる前提」を担保する3つの道具
AIで大量に変更を出す時代に、いちばんの安全装置は「いつでも戻れる」という状態です。ここでは、戻るための道具を3つ紹介します。
道具1:git revert(安全に打ち消す)と git reset(危険)
まず大原則。みんなで共有しているブランチでは、git reset --hard で履歴を巻き戻してはいけません。
-
git revert <コミット>:そのコミットの変更を打ち消す新しいコミットを作る。履歴は残る。だから共有ブランチでも安全。 -
git reset --hard <コミット>:そこまで履歴を巻き戻して、後ろを捨てる。手元の作業も消える。共有ブランチでやると、他の人の歴史と食い違って大事故。
# ⭕ 共有ブランチでの正解: 打ち消しコミットを積む
git revert a1b2c3d
# → "Revert: feat(cart): ..." という新コミットができる。安全。
# ⚠️ これは自分専用の未push ブランチでだけ
git reset --hard a1b2c3d
# 共有ブランチでやると、push 済みの歴史を壊して周りを巻き込む
git reset --hard と git push --force は、共有ブランチでは原則禁止です。やるなら「自分だけの未pushブランチ」に限定し、チームで共有しているブランチへの強制操作は、人間が二重確認するゲートにしてください。
atomic commit が効いてくるのはここです。1コミット1目的なら、git revert で「その変更だけ」をピンポイントで打ち消せる。tangledなコミットだと、revertした瞬間に欲しい変更まで一緒に消えます。
道具2:git bisect(バグの“犯人”を二分探索する)
「いつの間にかバグってる。でもどのコミットが原因か分からない」。AIが大量にコミットを積んだ後、これ本当に起きます。そんな時の魔法が git bisect。
仕組みは二分探索です。「正常だった過去のコミット」と「壊れている今のコミット」を教えると、gitが真ん中のコミットへ連れて行ってくれる。あなたは「これは正常?壊れてる?」と答えるだけ。これを繰り返すと、100コミットでも7回くらいで犯人にたどり着きます。
# 探索開始
git bisect start
# 今は壊れている
git bisect bad
# このコミットでは正常だった(例: 1つ前のリリースタグ)
git bisect good v1.4.0
# → git が中間コミットへチェックアウトする。
# 動作確認して、正常なら good、壊れてたら bad を答える
git bisect good # または git bisect bad
# 犯人が特定できたら終了して元に戻る
git bisect reset
テストが自動化されていれば、判定すら自動にできます。
# テストスクリプトの終了コードで good/bad を自動判定
# (終了コード 0 = good, 1〜127 = bad)
git bisect start HEAD v1.4.0
git bisect run npm test
# → git が自動で全部試して、最初に壊れたコミットを教えてくれる
これ、1コミットが小さいほど威力が出ます。犯人コミットが「機能追加+リファクタ+整形の全部入り」だと、特定できても「で、この中のどれや?」になる。atomic commitの恩恵、ここでも効いてきます。
道具3:feature flag(コードは入れる、でも挙動はオフにしておく)
大きな変更を「マージはするけど、まだ動かさない」状態にしておく技です。これがあると、問題が出てもコードを戻さずにスイッチを切るだけで済みます。
// 設定で機能のON/OFFを切り替える
const flags = {
newCheckout: process.env.FEATURE_NEW_CHECKOUT === "on",
};
export function checkout(cart: Cart) {
if (flags.newCheckout) {
return newCheckout(cart); // AIが書いた新ロジック
}
return legacyCheckout(cart); // 既存の安定ロジック
}
新しいコードに問題が出ても、FEATURE_NEW_CHECKOUT を off にすれば即座に旧挙動へ戻る。revertすら不要。戻る道を何本も用意しておくと、攻めの一歩が軽くなるんです。
CIで「履歴の質」をチームで守る
ここまでの原則、個人の心がけだけだと、忙しい日にすぐ崩れます。だから仕組みで守る。CI(自動チェック)に組み込んでしまいましょう。
コミットメッセージの型を強制する(commitlint)
commitlint を使うと、Conventional Commits の形になっていないコミットを弾けます。
// commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [2, "always", [
"feat", "fix", "refactor", "docs",
"test", "chore", "style", "build", "ci",
]],
"subject-max-length": [2, "always", 72],
},
};
これを git hook(コミット時の自動チェック)につなぎます。husky や lefthook を使うのが定番です。
# lefthook.yml の例
# commit-msg フックで、毎回メッセージの型をチェックする
# lefthook.yml
commit-msg:
commands:
lint-commit:
run: npx commitlint --edit {1}
これで、update みたいな雑なメッセージはコミット時点で止まります。最初は「うるさいな」と思うけど、1週間で慣れて、半年後に感謝します。
PRサイズと型をCIゲートにする
GitHub Actions で、PR全体のコミット型チェックと、巨大PRの警告を入れておきます。
# .github/workflows/commit-quality.yml
name: commit-quality
on: pull_request
jobs:
lint-commits:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with: { node-version: "20" }
- run: npm ci
# PRに含まれる全コミットのメッセージ型を検査
- run: npx commitlint --from origin/${{ github.base_ref }} --to HEAD
warn-large-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: 差分行数が多すぎないか確認
run: |
CHANGED=$(git diff --shortstat origin/${{ github.base_ref }}...HEAD \
| grep -oE '[0-9]+ insertion|[0-9]+ deletion' \
| grep -oE '[0-9]+' | paste -sd+ - | bc)
echo "変更行数: ${CHANGED:-0}"
if [ "${CHANGED:-0}" -gt 500 ]; then
echo "::warning::PRが大きすぎます(500行超)。分割を検討してください"
fi
ここで大事なのは、巨大PRは「失敗(block)」じゃなく「警告(warning)」にしておくこと。事情があって大きくなることはあるので、機械で頭ごなしに止めず、人間に「ほんまにこのサイズでええ?」と問いかける形にします。責める軸じゃなく、気づきの軸で。
Conventional Commits からリリースを自動化する
型がそろっていると、semantic-release のようなツールで「型からバージョンを決めて、CHANGELOGを生成して、タグを打つ」まで自動化できます。feat が入ったらマイナー、fix ならパッチ、BREAKING CHANGE ならメジャー。地道な型づけが、リリース作業の自動化という形で利息を生むわけです。コツコツが効いてくる。
人間とAI、どう役割を分けるか
ここまでを一枚にまとめます。AI時代のコミット運用で、何を人間が握り、何をAIに任せるか。
| 工程 | 人間が握る(What / Why) | AIに任せる(How) |
|---|---|---|
| コミットの分割 | 「どこが意味の境界か」の最終判断 | 分割案・hunkの仕分け候補 |
| コミットメッセージ | 「なぜそうしたか(Why)」の注入 | 件名・本文の下書き |
| PRの単位 | 「1PR1目的」かの判断、分割の決定 | 説明文・確認手順の下書き |
| レビュー | 受け入れ/差し戻しの決定、設計妥当性 | 差分の要約、観点の洗い出し |
| ロールバック | revert/resetの選択、影響範囲の判断 | bisect用テストの生成、手順の下書き |
| 不可逆操作 | force push・履歴改変・公開の承認 | (実行しない。提案までで止める) |
一言でいうと、「何を・なぜ変えたか」は人間、「どう書くか」はAI。コミットの意図とレビューの判断は、AIに渡しちゃいけない、人間の仕事です。逆にいうと、ここさえ握っていれば、書く作業はどんどん任せていい。
ありがちな落とし穴6つと、撤退ライン
落とし穴
- AIの1生成=1コミットにしてしまう:生成の単位とコミットの単位は別。意味で割り直す。
- メッセージにWhyを書かない:差分でWhatは分かる。本文には「なぜ」を残す。
- 巨大PRを機械で頭ごなしにblock:事情がある時もある。警告にして人間に判断を戻す。
-
共有ブランチで
reset --hard/--force:履歴を壊して周りを巻き込む。共有ではrevert。 - AIメッセージを鵜呑み:差分と食い違う“それっぽい嘘”が混ざる。根拠を照合してから採用。
-
ルールを盛りすぎて形骸化:最初から型を20個も決めない。
feat/fix/refactor/docs/test/choreくらいから始める。
撤退ライン(やりすぎを止める基準)
- 規約が目的化してきたら緩める:「キレイな履歴」が目的じゃない。「後から助かる」が目的。手段が重くなったら間引く。
- 小さくしすぎて文脈が散ったら戻す:atomicは大事だけど、1行ずつコミットして意味が追えないなら本末転倒。「これ以上分けたら意味が壊れる」が最小単位。
- 不可逆操作は必ず人間ゲート:force push、履歴改変、本番への公開・デプロイ・タグ削除は、AIに自動実行させない。提案までで止める。
安全の話(ここだけは絶対)
最後に、コミットまわりで事故ると痛いポイントを。
秘密情報を、コミットにもコミットメッセージにも絶対に入れない。
APIキー、トークン、パスワード、.env の中身、個人情報、社内固有のIDやURL。一度コミットしてpushすると、後で消しても履歴やフォーク、キャッシュに残る前提で考えてください。.gitignore と、gitleaks のような秘密検知をpre-commit/CIに入れて、混入を入口で止めるのが基本です。
そのほかの鉄則:
- AIに差分を貼る=外に情報を出す、という意識を持つ。秘密や個人情報を含む差分を、無自覚に外部サービスへ貼らない。
- AIが生成したコミットメッセージ・PR説明は「主張」であって「事実」じゃない。差分と照合してから採用する。下のレビュー用プロンプトが役立ちます。
- 不可逆操作(force push・履歴の書き換え・公開・デプロイ)は人間の承認ゲートを必ず通す。AIに自動でやらせない。
あなたはコミットの安全レビュアーです。以下のコミット(メッセージ+diff)を点検し、
次を報告してください。最終判断は人間が行う前提で、断定ではなく指摘として挙げること。
チェック項目:
1. 秘密情報の混入: APIキー/トークン/パスワード/個人情報らしき文字列はないか
2. メッセージと差分の不一致: 件名が言っていることと、実際の変更がズレていないか
3. tangled: 1コミットに無関係な複数の変更(機能+リファクタ+整形)が混ざっていないか
4. 破壊的変更: 公開API・DBスキーマ・設定の互換性を壊す変更が含まれていないか
出力: 上記4項目について「問題なし / 要確認(理由)」を一覧で。
確信が持てないものは「要・人間確認」と明記する。
--- コミット ---
{メッセージと diff を貼る}
おわりに:今日のコミットは、明日の自分への置き手紙
長くなったので、最後にぎゅっとまとめます。
AIで「書く」は速くなった。でも「読む・レビューする・戻す」は、人間の仕事として残った。そして、その土台になるのが、コミットとPRの設計でした。
- atomic commit:1コミット1意味。レビューも巻き戻しも、ぜんぶこれが効いてくる。
- Conventional Commits:型をつけると、人にも機械にもAIにもやさしい。
- コミットメッセージのWhy:差分に書けない「なぜ」を残す。
- 小さなPRと、戻れる道具(revert / bisect / feature flag):戻れる安心が、攻めの一歩を軽くする。
- CIで仕組み化:心がけは崩れる。だから自動チェックに守ってもらう。
ぜんぶに共通しているのは、「未来の自分とチームのために、今ちょっと整えておく」という姿勢です。
僕がいつも軸にしている問いがあって。「この選択、明日の自分が“あざっす”って言ってくれる方はどっちかな?」。コミットメッセージにWhyを2行足すのも、PRを小さく割るのも、まさにこれなんですよね。今日の自分がほんの少し手間をかけると、半年後の自分(や引き継いだ誰か)が「うわ、ちゃんと書いといてくれてあざっす」ってなる。コミットは、未来の自分への置き手紙。責める軸じゃなくて、思いやりの軸で残しておく。
そしてもう1つ。コードを書く速さは、AIでみんな横並びになっていきます。でも、「後から読める・戻せる・チームで扱える履歴を設計する力」は、簡単には奪われない、積み上がっていく資産だと思うんです。何を・なぜ変えたか(What / Why)を握るのは人間、どう書くか(How)はAIに任せる。この分担ができる人が、これからのAI時代に強い気がしています。
最後に、明日からの小さな4ステップを置いておきます。
-
次のコミットだけ、Conventional Commits の型(
feat:fix:など)をつけてみる。 - そのコミットの本文に、「なぜ」を1行だけ足してみる。
- AIが大きな差分を出したら、
git add -pで2つに割ってみる。 - 「もし問題が出たらどう戻すか」を、PR説明に1行書いてみる。
これだけで、明日の自分はきっと「あざっす」って言ってくれます。全部いっぺんにやらなくて大丈夫。65点でいいんです。1個ずつ、いきましょう。
参考にした考え方・出典
- Conventional Commits(conventionalcommits.org)
- Google Engineering Practices — Code Review Developer Guide「Small CLs」
- git 公式ドキュメント(
git revert/git reset/git bisect/git add -p) - AI支援開発でPRが大型化・レビュー負荷が増す傾向に関する各種調査・ベンダーレポート(2026)
- ツール: commitlint / husky / lefthook / semantic-release / gitleaks