AIに大規模リファクタリングを任せる方法|差分を小さく分割して壊さない手順

AIに大規模リファクタリングを任せる方法|差分を小さく分割して壊さない手順 AI開発

Claude Code、Codex、Gemini CLIなどのAIコーディングツールは、数十ファイルにまたがるリファクタリングまで一度に実行できるようになっています。

たとえば、

依頼例
このプロジェクトのAPI層を整理して、
重複コードをなくし、
型定義も統一してください。

と依頼すれば、AIは関連ファイルを探し、関数を移動し、Interfaceを書き換え、Importを修正し、テストまで変更できます。

しかし、大規模リファクタリングで重要なのは「AIが何ファイル変更できるか」ではありません。

変更量を人間が確認できる大きさに抑えながら、途中の各時点で正常動作を確認できるかが重要です。

AnthropicのClaude Code公式ドキュメントでも、リファクタリングでは変更を小さくテスト可能な単位で進め、変更後にテストを実行する方法が案内されています。

OpenAIのCodex公式Best Practicesでも、複雑な変更では実装前に計画し、完了条件としてテスト、Lint、型チェック、Diff Reviewなどを明確にすることが推奨されています。

この記事では、数十~数百ファイルに影響するリファクタリングをAIへ任せるときに、一括変更で壊さず、小さな差分へ分割して安全に進める方法を解説します。Claude Code単体での4フェーズワークフローやStrangler Figパターンの詳細はClaude Codeでリファクタリング完全ガイドで解説しているため、この記事では複数ツール横断でのDiff粒度・Commit設計に焦点を当てます。

スポンサーリンク
  1. 大規模リファクタリングを一度に依頼すると危険な理由
  2. リファクタリングでは「動作を変えない」が基本になる
  3. 最初に現在の状態をGitで固定する
  4. 大規模変更専用のブランチを作る
  5. 大規模な作業ではgit worktreeも使いやすい
  6. いきなり編集させず最初は調査だけさせる
  7. Plan Modeを使って実装前に変更内容を見る
  8. AIにはファイル単位ではなく依存関係単位で分割させる
  9. 変更計画を「レビュー可能な単位」まで細かくする
  10. 「ついでの改善」を禁止する
  11. フォーマット変更とロジック変更を混ぜない
  12. Renameとロジック変更も分ける
  13. 依存パッケージ更新も別にする
  14. 最初に既存テストを実行する
  15. テストが不足しているコードは先にテストする
  16. テスト変更と本体変更を同時に許可しすぎない
  17. 1ステップ終わるたびにDiffを見る
  18. git diff –statで変更量を先に確認する
  19. git add -pで必要な差分だけステージする
  20. 1つのCommitには1つの意味を持たせる
  21. Commitする前にAI自身へDiff Reviewさせる
  22. Codexでは「実装してから/review」を1セットにする
  23. Claude CodeではPlan ModeとWorktreeを組み合わせる
  24. Gemini CLIではPlan ModeとCheckpointingを利用できる
  25. AIにCommitさせるならCommit前の条件を明示する
  26. 完了条件をプロンプトへ具体的に書く
  27. AGENTS.mdやCLAUDE.mdへ恒久ルールを入れる
  28. ファイル数だけでなく変更行数にも目安を持つ
  29. 「まず全部書き換えてから直す」は避ける
  30. 新旧実装を一時的に共存させる
  31. Feature Flagを使える変更なら段階移行する
  32. DB変更を伴う場合は特に一括変更しない
  33. API変更でも互換性を先に考える
  34. 並列Agentへ同じ領域を触らせない
  35. AIへ途中で質問し直す
  36. 最後に全体テストを実行する
  37. 最終DiffはBase Branchとの差分で確認する
  38. AIへリファクタリングを依頼するプロンプト例
  39. 1ステップ完了後のレビュー用プロンプト
  40. AIによる大規模リファクタリングで避けたいプロンプト
  41. リファクタリング中に失敗したらAIへ追加修正させ続けない
  42. Gemini CLIのCheckpointも復旧ポイントとして使える
  43. 大規模リファクタリングは「AIに全部書かせる作業」ではない
  44. AIに大規模リファクタリングを任せるときのよくある質問
  45. まとめ

大規模リファクタリングを一度に依頼すると危険な理由

AIへ、

危険な依頼
src以下を全部リファクタリングしてください。
古い設計も直して、
型も整理して、
テストも更新してください。

と依頼すると、一見きれいなコードが大量に生成されることがあります。

問題は変更後です。

たとえば50ファイル、3,000行のDiffが生成され、その状態でテストが失敗したとします。

原因は、

可能性のある原因
関数移動
型変更
API変更
Import変更
ライブラリ更新
テスト変更

のどこにあるのでしょうか。

変更を同時に行うほど、原因の特定が難しくなります。

AIへさらに、

追加依頼
テストが失敗しているので直してください

と依頼すると、最初のリファクタリングによる不具合を修正するのではなく、失敗したテスト側を新しい実装へ合わせて変更してしまうこともあります。

その結果、

危険なパターン
実装変更
↓
テスト失敗
↓
AIがテストを変更
↓
テスト成功

となっても、本当に以前と同じ振る舞いを維持できているのか分からなくなります。

大規模リファクタリングでは、AIの能力より変更を分割する設計のほうが重要です。

リファクタリングでは「動作を変えない」が基本になる

リファクタリングは、基本的には外部から見える振る舞いを維持したまま内部構造を改善する作業です。

たとえば、

変更前
export function calculatePrice(
  price: number,
  quantity: number,
): number {
  return price * quantity;
}

を、

変更後
type PriceCalculation = {
  price: number;
  quantity: number;
};

export function calculatePrice({
  price,
  quantity,
}: PriceCalculation): number {
  return price * quantity;
}

へ変えるだけなら、計算結果そのものは変更していません。

しかし大規模リファクタリング中に、

仕様変更になってしまう例
return (
  price *
  quantity *
  1.1
);

まで変更すれば、もはや構造変更だけではありません。

AIへ依頼するときには、

プロンプト例
外部仕様と既存の振る舞いは変更しないでください。
今回は内部構造だけを変更してください。
仕様変更が必要だと思った場合は実装せず、
理由だけ報告してください。

のように、リファクタリングと仕様変更を明確に分離します。

Claude Codeの公式リファクタリング例でも、既存動作を維持したまま変更し、変更後にテストする流れが示されています。

最初に現在の状態をGitで固定する

AIへ大規模変更を許可する前に、現在のWorking Treeを確認します。

状態確認
git status

Gitのgit statusでは、HEAD、Staging Area、Working Treeの差分やUntracked Fileを確認できます。

すでに自分の変更が残っている状態でAIへ作業させると、

混在する変更
自分が変更した部分

と、

AIの変更
AIが変更した部分

が同じDiffへ混ざります。

可能なら開始時点をCleanにします。

確認
git status

で、

目標とする状態
nothing to commit,
working tree clean

になっている状態が分かりやすいでしょう。

未完成の作業を残したい場合は、Commit、Stash、Worktreeなどで分離します。

Gitのstashは現在のWorking DirectoryとIndexの状態を保存し、一時的にCleanなWorking Directoryへ戻す機能です。

大規模変更専用のブランチを作る

次に、リファクタリング専用Branchを作ります。

ブランチ作成
git switch -c refactor/user-service

大規模変更をMain Branch上で直接進める必要はありません。

AIが想定外の変更をしても、Branchを破棄すれば元の状態へ戻れます。

さらに変更が長期化する場合は、Main側の通常開発とリファクタリングを分離できます。

重要なのは、

重要な状態
元に戻せる

状態を作ってからAIへ編集権限を渡すことです。

大規模な作業ではgit worktreeも使いやすい

AIによるリファクタリングを通常の開発環境から完全に分離したい場合はgit worktreeも利用できます。

worktree作成
git worktree add \
  ../project-refactor \
  -b refactor/user-service

Gitは1つのRepositoryから複数のWorking Treeを作ることができ、それぞれ別BranchをCheckoutできます。

通常開発を、

通常開発
/project

で続けながら、

AIの作業場
/project-refactor

ではAIに大規模変更を任せられます。

Claude CodeにもWorktreeを利用した並列Session機能があり、各Sessionのファイル編集を別Working Treeへ分離できます。

CodexのChatGPTデスクトップアプリにもWorktreeを利用して複数の独立した作業を分離する機能があります。

Gemini CLIにもWorktree機能がありますが、2026年8月時点ではExperimentalとして提供されています。

いきなり編集させず最初は調査だけさせる

大規模リファクタリングで最初にAIへ依頼するのは、

違う
コードを書いてください

ではありません。

まず現在の構造を調べさせます。

たとえばUser Serviceを整理したいなら、

調査依頼例
まだファイルを変更しないでください。
User機能について、Controller、Service、Repository、
型定義、テスト、呼び出し元を調査してください。
依存関係と変更の影響範囲を整理してください。

と依頼します。

AIが最初から編集を始めると、コードベース全体を理解する前に局所的な改善を進めてしまうことがあります。

最初に、

把握すべき項目
どのファイルが関係するか

どこから呼ばれているか

Public APIは何か

既存テストはどこか

変更してはいけない境界は何か

を把握させます。

Claude Codeの公式Workflowでも、大規模なコードベースでは最初に関連ファイルを探し、コンポーネント同士の関係や実行フローを理解してから変更する方法が案内されています。

Plan Modeを使って実装前に変更内容を見る

AIコーディングツールにPlan Modeがある場合は、大規模リファクタリングと相性がよい機能です。

Claude Codeでは、

Plan Mode起動
claude --permission-mode plan

でPlan Modeを開始できます。

Plan ModeではClaudeはファイルを読み取って計画を作りますが、承認するまではファイルを書き換えません。

Codexでも複雑な作業ではPlan Modeが推奨されており、実装前にContextを集め、計画を作成できます。

Gemini CLIにもRead-onlyのPlan Modeがあります。

Plan Mode起動
gemini --approval-mode=plan

から起動でき、複雑な変更を実装する前にコードベースを調査できます。

ツールが違っても考え方は同じです。

大規模な変更ほど、「調査 → 計画 → 実装」の順に分離します。

AIにはファイル単位ではなく依存関係単位で分割させる

変更を小さくするというと、

単純な発想
1ファイルずつ変更

と考えがちですが、必ずしも正解ではありません。

1つのInterfaceを変更すると、実装クラスとテストも同時に変更しないとBuildできない場合があります。

そのためAIには、

依頼例
各ステップの終了時にBuildまたはTestが通る単位へ分割してください。

と依頼します。

たとえば、

不十分な単位
User型を変更

だけでは途中状態が壊れるなら、

適切な単位
User型
↓
Mapper
↓
Repository
↓
関連テスト

までを1ステップにします。

重要なのは、

重要ではないこと
変更ファイル数が少ないこと

そのものではなく、

重要なこと
各ステップ終了時にRepositoryが正常な状態であること

です。

変更計画を「レビュー可能な単位」まで細かくする

AIが次のようなPlanを出したとします。

大きすぎるPlan
1. User Serviceを整理する
2. Repositoryを整理する
3. テストを修正する

まだ大きすぎます。

「User Serviceを整理する」だけで10ファイル以上変わる可能性があります。

もう一段細かくします。

たとえば、

Step 1
User Service内の重複Validationを1つの関数へ集約

という変更だけを最初に行います。

次に、

Step 2
Controllerから直接呼ばれているDB処理をRepositoryへ移動

を行います。

その次に、

Step 3
User DTOの重複型を共通型へ統合

します。

このように、1つの変更に1つの目的だけを持たせます。

「ついでの改善」を禁止する

AIはコードを読んでいる途中に別の改善点を見つけます。

たとえばServiceをリファクタリングしている最中に、

誘惑される例
この関数名も変えたほうがよい

古いライブラリも更新したほうがよい

ESLint設定も変えたほうがよい

テストUtilityも整理したほうがよい

と判断する可能性があります。

これらを同時に実行するとDiffが急激に膨らみます。

プロンプトへ、

制約例
今回のステップに直接必要な変更以外は行わないでください。
別の改善点を見つけた場合はコードを変更せず、
最後に「別タスク候補」として報告してください。

と入れておきます。

これだけでもDiffがかなり読みやすくなります。

CodexのBest Practicesでも、Goal、Context、Constraints、Done whenを明確にすることでScopeを保ち、Assumptionを減らしてReviewしやすい変更を作ることが推奨されています。

フォーマット変更とロジック変更を混ぜない

大規模リファクタリングで特にDiffを読みにくくするのがFormattingです。

たとえばPrettier設定を変更すると、

本当の変更
本当に変更した10行

を見るために、

ノイズ
Formatterが変更した2,000行

を読むことになります。

AIへ、

指定例
Formattingだけの変更は行わないでください。
既存Formatter設定を維持してください。

と指定します。

Import順序の全面変更、Quote変更、改行変更、Rename、ロジック変更も可能なら別Commitに分けます。

Diffのノイズを減らすと、人間が本当に確認すべき変更を見つけやすくなります。

Renameとロジック変更も分ける

たとえば、

getUser()
getUser()

を、

findUserById()
findUserById()

へRenameするとします。

このRenameと同時に内部処理まで変更すると、

判断しづらい状態
名前が変わっただけなのか

ロジックも変わったのか

がDiffから判断しにくくなります。

まずRenameだけ行います。

Commit A
getUser → findUserById

この時点では動作を変えません。

次のCommitで、

Commit B
findUserById内部をRepositoryへ移動

します。

このような機械的変更と意味的変更の分離は、大規模リファクタリングのレビューを大幅に楽にします。

依存パッケージ更新も別にする

AIが古いコードを整理していると、

AIの判断例
このライブラリは古いので最新版へ更新します

と判断することがあります。

しかしPackage Updateは、それだけで別のFailure要因になります。

たとえば、

同時変更の例
Service構造変更
+
React Major Update
+
TypeScript Update

を同時に行ったあとBuildが壊れたら、原因を特定しにくくなります。

必要なDependency Updateがあるなら、リファクタリングの前か後に独立した変更として行います。

「構造変更」と「Runtime/Library Behaviorの変更」を混ぜないことが重要です。

最初に既存テストを実行する

変更後にTestを実行するだけでは不十分です。

変更前にも実行します。

テスト実行
npm test

必要なら、

追加確認
npm run lint
npm run typecheck
npm run build

も実行します。

ここで既存のFailureを把握します。

変更前から3Test失敗しているのに、変更後にも3Test失敗していた場合、

限らない
リファクタリングによって壊れた

とは限りません。

Baselineがないと判断できません。

Codex公式Best Practicesでも、変更後には関連テスト、Lint、Formatting、Type Checkなどを実行し、最終的な動作とDiffを確認するWorkflowが推奨されています。

テストが不足しているコードは先にテストする

大規模リファクタリング対象にTestがほとんどない場合は、すぐ内部構造を変更しないほうが安全です。

まず現在の振る舞いを固定するTestを追加します。

たとえば古い関数が、

src/normalize-name.ts
export function normalizeName(
  value: string,
): string {
  return value
    .trim()
    .toLowerCase();
}

だったとします。

リファクタリング前に、

normalize-name.test.ts
describe(
  "normalizeName",
  () => {
    it(
      "前後の空白を除去する",
      () => {
        expect(
          normalizeName(
            "  Alice  ",
          ),
        ).toBe(
          "alice",
        );
      },
    );
  },
);

のように現在のBehaviorを固定します。

このTestが正しい仕様を表していることを人間が確認したあとで内部実装を変更します。

AIに、

依頼例
まだ本体を変更しないでください。
現在の外部動作を固定するテストだけ追加してください。

と依頼する方法もあります。

テスト変更と本体変更を同時に許可しすぎない

AIへ、

危険な依頼
リファクタリングして、
失敗したテストも直してください

と依頼すると、危険な場合があります。

本体コードのBugを修正する代わりに、

変更前
expect(
  result,
).toBe("old");

を、

危険な変更
expect(
  result,
).toBe("new");

へ変えてTestを成功させることができるからです。

まず既存Testを原則固定します。

テスト変更が必要になった場合は、

制約例
既存テストを変更する必要がある場合は、先に理由を説明してください。
承認なしに期待値を変更しないでください。

と指定します。

これはBehaviorを維持するリファクタリングでは特に重要です。

1ステップ終わるたびにDiffを見る

AIが小さな変更を終えたら、すぐ次へ進ませません。

まず、

Diff確認
git diff

を確認します。

人間が見るポイントは、コードの美しさだけではありません。

「依頼した範囲以外が変更されていないか」を最初に確認します。

たとえば、

依頼範囲
src/user/service.tsだけを変更

と依頼したのに、

想定外の変更
package.json
tsconfig.json
auth.ts
database.ts

まで変わっているなら、理由を確認します。

大規模リファクタリングでは、Diff Reviewを工程の最後ではなく各ステップの途中へ入れることが重要です。

git diff –statで変更量を先に確認する

いきなり全文Diffを読む前に、

変更量確認
git diff --stat

で変更量を確認できます。

たとえば、

レビューしやすい例
5 files changed,
84 insertions(+),
61 deletions(-)

なら比較的レビューしやすい変更です。

一方、

大きすぎる例
83 files changed,
4291 insertions(+),
3877 deletions(-)

になっているなら、本当に1ステップとして適切なのか疑います。

「AIなら一度にレビューできる」ことと、「人間が安全にMergeできる」ことは別です。

git add -pで必要な差分だけステージする

1ファイル内に複数の変更が混ざってしまった場合は、

部分ステージ
git add -p

を利用できます。

Gitのgit add -pでは、ファイル全体ではなく変更の一部分だけをStaging Areaへ追加できます。

たとえばAIが同じファイルで、

必要な変更
必要な関数移動

と、

不要な変更
不要なコメント整理

を同時に行った場合、必要なHunkだけをStageできます。

AI AgentにCommitまで任せる場合でも、最終的にはStaged Diffを確認する習慣を付けると安全です。

1つのCommitには1つの意味を持たせる

大規模リファクタリングを安全に進めるうえで、Commitは単なる履歴ではなく復旧ポイントになります。

たとえば、

段階的なCommit
Step 1: Validation共通化 → Test → Commit

Step 2: Repository抽出 → Test → Commit

Step 3: 型定義統一 → Test → Commit

と進めます。

Step 3で問題が発生しても、Step 2までは正常だと分かっています。

一方、3時間AIを動かして最後に1Commitだけ作ると、途中の正常状態が残りません。

Commitを細かくする目的はGit Historyを美しくすることだけではなく、AIの変更を途中で巻き戻せるようにすることです。

Commitする前にAI自身へDiff Reviewさせる

人間が確認する前に、AIへもう一度ReviewerとしてDiffを見せる方法もあります。

たとえば、

Review依頼例
今回の変更差分だけをレビューしてください。
リファクタリング前と外部動作が変わっていないか、
変更範囲外の編集、エラー処理の欠落、型の弱体化、
テスト不足を確認してください。
まだコードは修正しないでください。

と依頼します。

実装AgentとReviewerの役割を分離すると、同じSessionでそのまま、

危険な前提
自分の変更は正しい

という前提で修正を続けるより問題を見つけやすくなります。

Codexには/reviewがあり、Base Branchとの差分、Uncommitted Changes、特定Commitなどを対象として専用Reviewを実行できます。ReviewはWorking Treeを書き換えず、優先度付きの指摘を返します。

Codexでは「実装してから/review」を1セットにする

Codexを使う場合は、大規模リファクタリングを、

一連の流れ
1ステップ実装
↓
テスト
↓
/review
↓
人間がDiff確認
↓
Commit

という単位で進めると扱いやすくなります。

/reviewではUncommitted ChangesだけをReviewすることもできるため、現在の小さな差分だけを対象にできます。

50ファイル変更してからReviewするより、5ファイルずつReviewしたほうが、指摘された問題の原因も追跡しやすくなります。

Claude CodeではPlan ModeとWorktreeを組み合わせる

Claude Codeで大規模リファクタリングを行うなら、

構成例
Worktreeで隔離
↓
Plan Modeで調査
↓
計画を確認
↓
小さく実装
↓
テスト
↓
Diff確認

という構成が使いやすくなります。

Claude Codeの公式Workflowでは、Plan Modeは承認前に変更内容をReviewしたいケース向け、Worktreeは複数Sessionの編集を衝突させず分離する用途として案内されています。

4フェーズ(探索・計画・実装・検証)のプロンプト例やStrangler Figパターンによる段階的な稼働中システムの置き換え、worktreeを使ったJS→TSの並列マイグレーション手順はClaude Codeでリファクタリング完全ガイドで具体的なプロンプトとコード例つきで解説しています。

ツールへ長時間自由に作業させるより、人間がCheckpointを挟みながら進めるほうが大規模変更では安全です。

Gemini CLIではPlan ModeとCheckpointingを利用できる

Gemini CLIにもPlan Modeがあり、複雑な変更をRead-only状態で調査してから実装へ移れます。

さらにCheckpointing機能では、AIによるファイル変更の前にProject StateのSnapshotを保存できます。

Gemini CLIのCheckpointingは、AI Toolがファイルを書き換える前にShadow Git RepositoryへSnapshotを作成し、会話履歴やTool Callも保存します。

これによって失敗した変更を以前の状態へ戻しやすくなります。

ただし、AIツール独自のCheckpoint機能だけに依存せず、自分のGit BranchやCommitも残しておくほうが他ツールへ移行した場合にも履歴を追いやすくなります。

AIにCommitさせるならCommit前の条件を明示する

AI AgentへGit操作まで許可する場合は、

曖昧な依頼
適当に区切ってCommitしてください

ではなく、Commit条件を指定します。

たとえば、

実装依頼例
1つの目的だけを完了した時点で停止してください。
関連テスト、Type Check、Lintが成功したことを確認してください。
その後Diffを要約し、まだCommitはしないでください。

とします。

人間が確認したあと、

Commit指示
この差分だけをCommitしてください。
次のステップには進まないでください。

と依頼します。

AIが、

避けたい自動連鎖
Commit
↓
次の変更
↓
Commit
↓
次の変更

を自動で長時間続ける状態を避けられます。

完了条件をプロンプトへ具体的に書く

「きれいにリファクタリングしてください」では完了条件が曖昧です。

AIがどこまで変更すべきか判断できません。

たとえば、

明確な依頼例
UserServiceからDB直接アクセスをなくし、
すべてUserRepository経由にしてください。
Public APIの引数と戻り値は変更しないでください。
既存テストの期待値は変更しないでください。
TypeScriptの型チェックとUser関連テストが
成功した時点で終了してください。
ほかのServiceは変更しないでください。

とすると、終了条件がかなり明確になります。

Codex公式Best Practicesでも、PromptにはGoal、Context、Constraintsに加えて「Done when」を明示することが推奨されています。

大規模変更ほど「何をするか」だけではなく、「何をしたら止まるか」を書くことが重要です。

AGENTS.mdやCLAUDE.mdへ恒久ルールを入れる

毎回、

毎回入力するのは面倒
勝手に依存関係を更新しない
既存テストの期待値を変更しない
1ステップごとにテストする

と入力するのは面倒です。

CodexならAGENTS.mdへRepository固有の開発ルールを記述できます。

Codex公式では、AGENTS.mdにBuild/Test/Lint Command、Engineering Convention、制約、完了条件などを記録し、各Sessionで再利用する方法が案内されています。

たとえば次のようにできます。

AGENTS.md
# Refactoring Rules

大規模変更を一度に行わない。

各ステップ終了時に npm run typecheck と
関連テストを実行する。

既存テストの期待値は、
仕様変更の承認なしに変更しない。

依存パッケージの更新を
リファクタリングと同時に行わない。

別の改善点を見つけても、
今回のスコープ外なら変更しない。

Claude Codeなら同じ考え方をCLAUDE.md、Gemini CLIならGEMINI.mdへ記述できます。

Gemini CLIのGEMINI.mdはProject固有のInstructionやCoding StyleなどをContextとして与える仕組みです。

ファイル数だけでなく変更行数にも目安を持つ

「1ステップ最大5ファイル」のような制限は分かりやすいですが、ファイル数だけでは判断できません。

1ファイルが4,000行変更されることもあります。

逆にInterface Renameで20ファイルのImportを1行ずつ変更するだけなら、20ファイルでもレビューは簡単です。

そのため、

優先度低
ファイル数

より、

優先度高
変更目的の数

Diffを短時間で理解できるか

を重視します。

実務では、

目安
この変更をPR Reviewで説明するとしたら、一文で説明できるか

を目安にすると分割しやすくなります。

一文で説明できないなら、複数の変更が混ざっている可能性があります。

「まず全部書き換えてから直す」は避ける

AIは速度が速いため、

危険な手順
一度理想形へ全部変更
↓
エラーを順番に直す

という方法を取りやすくなります。

たとえばInterfaceを先に全面変更すると、

混乱状態
TypeScript Error 184件

の状態になることがあります。

そこからAIが順番に修正すれば最終的にはBuildできるかもしれません。

しかし途中状態では何が正しいのか判断できません。

可能なら、

安全な手順
新しいInterfaceを追加
↓
一部の実装を移行
↓
テスト
↓
次の実装を移行
↓
テスト
↓
旧Interfaceを削除

というIncremental Migrationにします。

新旧実装を一時的に共存させる

大規模リファクタリングでは、一気に旧APIを削除する必要はありません。

たとえば、

src/get-user.ts
export function getUser(
  id: string,
) {
  // 旧実装
}

を新しいRepositoryへ移行するなら、最初に新APIを作ります。

src/user-repository.ts
export class UserRepository {
  async findById(
    id: string,
  ) {
    // 新実装
  }
}

その後、呼び出し元を少しずつ移行します。

すべて移行できてから旧関数を削除します。

この方法なら各段階でApplicationを動かせます。

AIへも、

依頼例
旧APIはまだ削除しないでください。
まず新しいRepositoryを追加し、
UserServiceだけを移行してください。

のように依頼します。

Feature Flagを使える変更なら段階移行する

リファクタリングによって実行経路そのものが変わる場合は、Feature Flagで新旧処理を切り替える方法もあります。

src/get-user.ts
if (
  config.useNewUserService
) {
  return newUserService
    .getUser(id);
}

return legacyUserService
  .getUser(id);

これなら新実装をDeployしても、問題があれば旧実装へ戻せます。

すべてのリファクタリングに必要ではありませんが、決済、認証、検索など影響範囲の大きいシステムでは「Codeを戻さず機能だけ戻せる」構造が役立ちます。

DB変更を伴う場合は特に一括変更しない

Database Schemaまで変更するリファクタリングでは、

危険な手順
Schema変更
↓
Application変更
↓
旧Column削除

を1Deployで行うとRollbackが難しくなる場合があります。

たとえば、

変更前
name

を、

変更後
first_name
last_name

へ分離する場合です。

最初に新Columnを追加します。

次に新旧両方へ対応できるApplicationへ変更します。

既存データをMigrationします。

新Columnへ完全移行したことを確認してから、最後に旧Columnを削除します。

AIへDatabase Migrationを任せる場合も、

依頼例
Column追加と旧Column削除を同じMigrationにしないでください。
旧VersionのApplicationと互換性を維持できる
段階移行案を先に出してください。

と依頼したほうが安全です。

API変更でも互換性を先に考える

内部リファクタリングのつもりでも、Public FunctionやHTTP APIを変更すると外部利用者へ影響します。

たとえば、

変更前
GET /api/user

を、

変更後
GET /api/users

へ変更する場合です。

AIがRepository内の呼び出し元をすべて修正しても、Repository外のMobile Appや外部Clientまでは修正できません。

大規模変更では、

これは違う
Repository内で検索して見つからない

ことと、

これとは限らない
誰も使っていない

ことを同一視しないようにします。

Public API、Database Schema、Event Name、Environment Variable、CLI Optionなどは特に慎重に変更します。

並列Agentへ同じ領域を触らせない

AI Agentは複数並列で動かせますが、

危険な並列化
Agent A: UserServiceを整理
Agent B: UserRepositoryを整理
Agent C: User型を整理

のように強く依存する領域を同時に変更するとMerge Conflictだけでなく、設計上の前提まで食い違う可能性があります。

並列化するなら変更領域を分離します。

たとえば、

安全な並列化
Agent A: User Module
Agent B: Notification Module

のように独立性が高い作業を分けます。

Git Worktreeを使えばファイル編集そのものを別Working Treeへ分離できます。

ただしWorktreeは設計上のConflictまで自動解決するものではありません。

共有Interfaceへ影響する変更は順番に行ったほうが安全です。

AIへ途中で質問し直す

大規模リファクタリングでは、最初に作ったPlanが最後まで正しいとは限りません。

コードを調査して初めて、

想定外の発見
想定していた依存関係と違う

ことが分かる場合があります。

そのときは当初Planを無理に続けず、

依頼例
ここまでの変更で判明した事実を整理してください。
当初の残りPlanをそのまま続けるべきか再評価してください。
まだコードは変更しないでください。

と依頼します。

Gemini CLIでは、複雑なPlan Mode Workflowの途中でユーザーがModel Steeringを使って方向修正できる機能も提供されています。

AI Agentは「最初に指示して最後まで放置」するより、重要な境界で人間が方向を確認する使い方のほうが大規模変更に向いています。

最後に全体テストを実行する

各ステップでは関連Testだけを実行すると高速です。

しかしすべてのリファクタリングが終わったら全体確認を行います。

Node.js/TypeScriptプロジェクトなら、たとえば、

全体確認
npm test
npm run typecheck
npm run lint
npm run build

を実行します。

E2E Testがあるならそれも実行します。

個々のModule Testが通っていても、Module間のIntegrationで壊れている可能性があるためです。

Codex公式Best Practicesでも、変更後に関連テスト、Lint、Formatting、Type Check、最終動作、Diffを確認することがReliability向上のWorkflowとして挙げられています。

最終DiffはBase Branchとの差分で確認する

各Stepを確認していても、最後に全体Diffを確認します。

全体Diff確認
git diff main...HEAD

ここで、

確認すべき項目
削除してはいけない処理

不要なDependency変更

Debug Code

一時的なTODO

設定ファイル変更

Testの期待値変更

などが混ざっていないか確認します。

CodexならBase Branchを指定して/reviewを実行することで、Branch全体の差分をReviewできます。

途中では小さなDiff、最後には全Diffという二段階Reviewが扱いやすくなります。

AIへリファクタリングを依頼するプロンプト例

大規模リファクタリングでは、最初から実装させず次のようなPromptから始められます。

調査・Plan依頼
User機能の大規模リファクタリングを行います。

まだコードを変更しないでください。

まず関連するController、Service、Repository、
型定義、テスト、呼び出し元を調査してください。

今回の目的は、
UserServiceからDBへの直接アクセスをなくし、
UserRepositoryへ集約することです。

外部API、戻り値、既存の動作は変更しません。

依存パッケージの更新、
無関係なRename、
Formatter変更は行いません。

実装は、各ステップ終了時に
型チェックと関連テストが通る単位へ分割してください。

各ステップについて、
変更対象、
変更理由、
影響範囲、
確認するテストを提示してください。

計画を確認するまではファイルを編集しないでください。

Planを確認したら、最初の1Stepだけ実行させます。

Step 1実装依頼
計画のStep 1だけ実装してください。

Step 2以降には進まないでください。

実装後に関連テストと型チェックを実行し、
変更ファイルと結果を報告してください。

テストの期待値は変更しないでください。

これだけでも、

比較対象
全部任せる

場合と比べて変更範囲をかなり制御できます。

1ステップ完了後のレビュー用プロンプト

実装後には、次のようにReviewさせます。

Review依頼
まだ追加修正しないでください。

現在のgit diffだけをレビューしてください。

今回の目的以外の変更が混ざっていないか、
外部動作が変わっていないか、
エラー処理が失われていないか、
型が弱くなっていないか、
既存テストが不自然に変更されていないかを確認してください。

問題がなければ、
この差分を1つのCommitとして確定してよい理由を説明してください。

「レビューしてください」の後に即修正まで許可せず、一度判断だけさせるのがポイントです。

AIによる大規模リファクタリングで避けたいプロンプト

次のような依頼は変更範囲が広すぎます。

曖昧例1
このコードを全体的にきれいにしてください。

「きれい」の定義がありません。

曖昧例2
ベストプラクティスに直してください。

も同様です。

何をBest Practiceと考えるかをAI側へ任せすぎています。

さらに、

曖昧例3
問題があれば全部修正してください。

とすると、リファクタリングからSecurity Fix、Dependency Update、FormattingまでScopeが広がる可能性があります。

大規模変更ほど自由度を上げるのではなく、1回の依頼で変更できる目的を狭くします。

リファクタリング中に失敗したらAIへ追加修正させ続けない

たとえばStep 3のあとTestが失敗したとします。

AIへ何度も、

依頼例
直して

と依頼すると、

膳大していくDiff
修正A
↓
別Test失敗
↓
修正B
↓
別の型Error
↓
修正C

とDiffが膨らむ場合があります。

数回の修正で原因が分からないなら、正常だった直前のCommitへ戻す判断も必要です。

巻き戻し
git reset --hard <正常なcommit>

などで戻せる状態を作っていることが、小さなCommitを残す大きなメリットです。

AIの作業時間を無駄にしたくないからと壊れた変更へ修正を積み重ねるより、原因が分かった段階で小さくやり直したほうが最終Diffも理解しやすくなります。

Gemini CLIのCheckpointも復旧ポイントとして使える

Gemini CLIのCheckpointingを有効にしている場合、AI Toolがファイルを変更する前の状態をSnapshotとして保存できます。

大規模変更を試す際の安全網として便利ですが、通常のGit Commitとは役割が異なります。

Git CommitはTeamで共有する変更履歴になります。

AI Tool固有のCheckpointは、Session中に試行錯誤を戻す用途として扱うと分かりやすいでしょう。

つまり、

使い分け
短期的な実験の復元 → AIツールのCheckpoint

レビュー済みの正常地点 → Git Commit

という使い分けができます。

大規模リファクタリングは「AIに全部書かせる作業」ではない

AIコーディングツールを使うと、コードを書く速度自体は大幅に上げられます。

その結果、開発者の役割は、

従来
1行ずつコードを書く

ことから、

これから
変更境界を設計する

ことへ移っていきます。

大規模リファクタリングで開発者が決めるべきなのは、

一部
何を変えるか

だけではありません。

他にも決めること
何を変えないか

どの単位で止めるか

どこでテストするか

どこなら戻れるか

まで決めます。

AIに自由度を与えるほど高速になりますが、ReviewできないDiffが生成されればMergeまでの時間はむしろ増える可能性があります。

AIに大規模リファクタリングを任せるときのよくある質問

QAIには何ファイルまで一度に変更させてよいですか

Aファイル数だけで決める必要はありません。20ファイルのImport Renameだけなら比較的確認しやすい一方、1ファイルでも500行のBusiness Logic変更なら慎重なReviewが必要です。「1ステップに1目的」「終了時にテスト可能」「Diffを人間が理解できる」を基準にします。

Q最初からAIに全部リファクタリングさせて後からレビューするのはダメですか

A小規模Repositoryなら成立する場合もあります。しかし大規模な変更では、不具合が見つかったときにどの変更が原因なのか追跡しにくくなります。AnthropicのClaude Code公式ドキュメントでも、リファクタリングは小さくテスト可能なIncrementで行うことが案内されています。

QClaude CodeならPlan Modeを使ったほうがよいですか

A複数ファイルにまたがる変更では有効です。Claude CodeのPlan Modeでは、ファイルを調査してPlanを作成しますが、承認するまでは編集しません。変更範囲を確認してから実装へ移れるため、大規模リファクタリングと相性があります。

QCodexではどう進めればよいですか

A複雑な作業ではPlan Modeで計画し、Goal、Context、Constraints、Done whenを明確にします。実装後は関連テスト、Type Check、Lintなどを実行し、/reviewでUncommitted DiffやBranch Diffを確認できます。

QGemini CLIでも元に戻せますか

ACheckpointingを有効にすると、AI Toolによるファイル変更前にProject StateのSnapshotが保存されます。ただし通常のGit BranchやCommitも併用するほうが、ツールに依存しない履歴を残せます。

QAIにテストまで修正させてよいですか

A新しいCode Pathに必要なTest追加はAIへ任せられます。一方、リファクタリングで既存Behaviorを維持する場合、失敗した既存Testの期待値をAIが自由に変更できる状態は避けます。期待値変更が必要なら、まず「なぜ仕様変更が必要なのか」を説明させて人間が確認します。

QAIにCommitまで任せてもよいですか

A可能ですが、Commit単位を明確に指定するほうが安全です。「各ステップの実装、テスト、Diff Reviewが終わったら停止し、人間の確認後にCommitする」というWorkflowなら、大規模な一括Commitを防げます。

まとめ

AIへ大規模リファクタリングを任せるときに重要なのは、

違う
高性能なモデルへ全部任せる

ことではありません。

重要なのは、AIが間違えても被害が小さい変更単位を作ることです。

最初に現在のWorking TreeをCleanにし、専用BranchまたはWorktreeで作業を分離します。

その後すぐ実装させず、関連ファイル、依存関係、Public API、既存テストを調査させます。

Claude Code、Codex、Gemini CLIにはいずれも複雑な作業を実装前に整理するPlan Modeがあり、大規模変更ではこうしたRead-onlyの計画フェーズを利用できます。

実装へ移ったら、一度に全体を書き換えません。

変更を「各段階でBuild・Testできる単位」へ分割し、1Stepだけ変更します。

そのたびに、

差分確認
git diff

で差分を確認し、関連Test、Type Check、Lintを実行します。

問題がなければCommitし、そのCommitを次の復旧地点にします。

機械的Rename、ロジック変更、Dependency Update、Formatter変更、仕様変更も可能な限り別々に扱います。

Codexでは変更後のDiffを/reviewで専用Review Agentへ確認させることもでき、Claude CodeではPlan ModeとWorktree、Gemini CLIではPlan ModeとCheckpointingを組み合わせられます。

大規模リファクタリングを安全に進める流れは、

全体の流れ
現在の正常状態を固定
↓
影響範囲を調査
↓
変更計画を作成
↓
1つの目的だけ実装
↓
テスト
↓
Diff Review
↓
Commit
↓
次の変更

です。

AIが一度に100ファイル書き換えられるとしても、100ファイルを一度に変更させる必要はありません。

AIコーディング時代の大規模リファクタリングでは、「どれだけ大量に変更できるか」より「どれだけ小さく安全に変更を確定できるか」が重要です。