開発claude-code-tools

未コミットの変更を15個の意味あるコミットに分割整理した記録

git status を開いたら、変更済み・新規・未追跡が画面いっぱいに並んでいた。数日ぶんの作業が一塊で溜まっていて、このまま git add . で一括コミットすると後で git log を見たときに何も思い出せなくなる。

そこで「gitignore すべきものはちゃんと無視に回す」「残りは意味のある単位でステージングしてコミットする」の2本立てで、作業ツリーを更地に戻すことにした。実装作業ではなく、散らかった机を引き出しごとに片付けるような一日。

最終的に 15個の意味あるコミットに分割し、.tmp-* を gitignore に追加し、残骸ファイルの生成元をスキル側まで遡って潰した。

まず全体像を掴ませる

いきなりコミット単位を切るのではなく、Claude Code に作業ツリーの全体像を調べさせた。変更済みファイル、新規ファイル、未追跡ディレクトリをそれぞれ分類してもらう。

調査の途中で、判断に迷うものがいくつか浮かび上がってきた。

  • --full-page という名前の不審なファイル(スクショ取得が失敗したときの誤生成ファイルだった)
  • memo/ 配下のスクラッチ候補
  • .claude/workflows/ のテスト出力

ここで一つ慣例を確認させたのが効いた。「memo/ 配下に PNG を置く慣例はあるか?」と調べさせると、追跡済みの PNG が156件あった。つまり「画像入りの作業メモはコミットして履歴に残す」のがこのリポジトリの慣例だと分かった。これで memo/ 配下を機械的に無視に回す選択肢は消えた。

依存関係を確認してからコミット単位を切る

新規ファイルをどうグルーピングするかは、ファイル名だけ見ても判断できない。なので「どのページがどの util / composable を使っているか」を先に追わせた。

結果、blog 記事4本と、それぞれに対応する utils / composable / test が1セットになっていることが分かった。これらは機能として一塊なので、1コミットにまとめる方が git log 上で意味が通る。

教訓: コミット単位は「ファイルの種類」で切るのではなく「機能の依存関係」で切る。ページとそれが依存する util・test は一緒に動く運命なので、一緒にコミットする。

調査の最中、作業ツリーに変更が増えていたのにも気づいた。beat-monitoring 関連の JSON が13件と、チャートの Vue コンポーネントが追加で変更されていた。初期スナップショットを過信せず、コミット直前にもう一度 git status を取り直させたのは正解だった。

gitignore は「何も足さない」と判断した

memo/ 配下のスクラッチ候補について、最初は「これは履歴に残さず gitignore すべきでは?」と判断を仰がれた。だが上で確認した「PNG 156件追跡済み」の慣例を踏まえると、ワークフローのテスト出力も note スライドの作業ディレクトリも、明日の振り返り用ログとして残す価値がある。

なので gitignore には何も足さず、これらは普通にコミットすることに決めた。.log は既に無視済みだったので対象外。

ここで一旦 gitignore の追加はゼロ件で確定した。だが、この判断は後で覆ることになる。

残骸 JSON の生成元をスキルまで遡る

memo/2026-05-20/x-search-eurekapu-raw.json という、X 検索の生 JSON ダンプが残骸として残っていた。これを単に削除するだけでは、また同じものが生成されてしまう。生成元を断たないと再発するので、出どころを追わせた。

追跡の流れはこうだった。

  1. /make-diary のステップが review-yesterday-tweets を呼んでいる → ここが書き出している?
  2. review-yesterday-tweets を確認 → 「標準出力のみ・ファイル化しない」方針だった。シロ
  3. 残るは x-search スキル側 → グローバルスキル(~/.claude/skills/x-search/SKILL.md、リポジトリ外)にあった
  4. 中身を読むと「出力先のメモ」というガイダンスが memo/{date}/x-search-{topic}.json への保存を推奨していた。これが犯人

つまり残骸の真因は、スキルのガイダンス文そのものだった。該当箇所が2つ(「結果をファイル保存」セクションと「出力先のメモ」)あったので、両方を「専用 tmp dir + 日付付き + 末尾で必ず削除」する形に書き換えた。

教訓: 散らかったファイルを掃除するときは、ファイルを消すだけでなく「なぜそれが生まれたか」を遡る。今回は生成元がリポジトリ外のグローバルスキルのドキュメントだった。これを直さないと、毎回同じ残骸が積もる。

スキルを直してから、残骸(X 検索の生ダンプ + 家電プレビューの連番 PNG)を削除した。memo/2026-05-20/a.htmlaa.html は既に追跡済みのファイルだったので、残骸ではないと判断して対象から外した。

14個に分けて順次コミット

分類が固まったので、コミットを順番に切らせた。最初は14個の予定だった。

#コミット内容
1誤生成された --full-page スクショファイルを削除
2blog 記事4本グループ(ページ・utils・composable・test・記事登録)
3beat-monitoring(DELL/NOW 追加 + 既存銘柄データ・チャート更新)
4OG 画像のリダイレクトループ修正グループ
5家電カードと Amazon リンク生成ユーティリティ
6make-diary 並列ワークフロー(コマンド・WF 本体・RUNBOOK・スモークテスト)
7vue-pages スキル更新
8ドキュメント(Chrome DevTools MCP の仕様追記 + issue 記録2件)
9〜13日記コンテンツを日付ごとに分割(05-25 / 26 / 27 / 28 / 29)
1405-28 の作業メモ(OG シークレット調査・note スライド作業ディレクトリ)

CLAUDE.md の変更が、Chrome DevTools MCP のデバッグ仕様についてのもので、これは 2026-05-26-chrome... の issue と対になっていることに気づいた。ドキュメントと issue は同じ文脈なので #8 に同梱した。

日記コンテンツは日付をまたいで溜まっていたので、content(2026-05-25) のように日付ごとに1コミットへ割った。後で「いつのぶんを足したか」が git log から一目で分かる。

最後に現れた .tmp-idx.png が15個目の引き金

全14コミットを終えて作業ツリーを確認すると、ほぼクリーンだった。ただ一つ、apps/web/.tmp-idx.png という見覚えのないファイルが残っていた。

調べさせると、このセッション中(11:14)に生成された184KB の PNG で、リポジトリのコードからは一切参照されておらず、git 履歴もない。.tmp- プレフィックスの自動生成一時ファイルだった。

これは典型的な gitignore 対象。「gitignore には何も足さない」とした序盤の判断を、ここで覆した。apps/web/.gitignore に1パターン追加して、残骸も削除した。

# 作業用の一時PNG(スクショ/インデックス画像など .tmp- プレフィックスで生成される)
.tmp-*

このコミット(chore(gitignore): 作業用一時PNG(.tmp-*) を無視対象に追加)が15個目になり、作業ツリーが完全に更地になった。push は未実施でローカルのみ。

振り返り

人間がやったのは「意味のある単位で切ってほしい」「gitignore すべきものは判断を仰いで」という方針の指示と、memo/ のスクラッチをどう扱うかの最終判断だけ。あとは全体像の調査から依存関係の確認、コミットの順次実行までを Claude Code に回させた。

途中で「gitignore には何も足さない」と決めたのに、最後に出てきた .tmp-idx.png で判断を覆したのが今日の小さな山場。作業ツリーは静的なスナップショットではなく、片付けている間にも変化する。コミット直前に git status を取り直す癖が効いた。

学び

  • コミット単位は「ファイルの種類」ではなく「機能の依存関係」で切る。ページ・util・test は一緒に動くので一緒にコミットする
  • 残骸ファイルは消すだけでなく生成元を遡る。今回はリポジトリ外のグローバルスキルのガイダンス文が真因だった
  • リポジトリの慣例(PNG 156件追跡済み = 画像入りメモはコミットする)を先に確認すると、gitignore の判断を機械的に間違えずに済む
  • 作業ツリーは片付け中にも増える。コミット設計は初期スナップショットを過信せず、直前に取り直す