
- AI エージェントが「忘れる」問題
- Git コマンドのおさらい
- キーコンセプト:二つのタイムライン
- 再現性の完全性と時系列からの解放
- Makefile による定型実行
- AI への指示書
- AI エージェントとの対話ログ(シミュレーション)
AI エージェントが「忘れる」問題
最近、AI エージェントとペアプロをするのが当たり前になってきました。彼らは驚くほど優秀ですが、長時間一緒に作業していると、ふとした瞬間に「さっき話したこと、もう忘れたの?」と寂しくなることはありませんか?
特にデータサイエンスの実験では、この「文脈の欠如」が致命傷になります。本記事では、Git worktree という「少しマニアック」な機能を使って、AI に記憶と整理整頓された実験ノートを授ける方法を解説します。
Git コマンドのおさらい
本手法の根幹を支える Git コマンドを説明します。
git branch: 歴史の分岐点。コードの「試作」を本番から切り離します。git switch: 世界線の移動。瞬時に異なるコード状態へ切り替えます。git checkout: 万能コマンド。ブランチ切り替えもファイル復元もこれ一本でしたが、役割が多すぎるため現在はswitch(切り替え)とrestore(復元)に分化しました。git worktree: 魔法の同期。一つのリポジトリから、特定のブランチ(ここではnotes)だけを別ディレクトリに「実体化」させます。これが「時空を超えた思考のアーカイブ」を実現する核となります。
キーコンセプト:二つのタイムライン
解決策の鍵は、Git のブランチ戦略とディレクトリ構造にあります。以下の二つの異なるタイムラインを管理します。
コード履歴 (
main,exp/*ブランチ)- 動作するソースコード、モデル定義、DVC ロックファイルを管理します。
- 実験ごとに
exp/YYYYMMDD_HHMMSSのようなブランチを切ります。
思考履歴 (
notesブランチ)- 実験計画書 (
spec.md)、実行結果と考察 (result.md) を管理します。 - Orphan Branch(孤立ブランチ) として作成し、メインのコード履歴とは一切混ざりません。
- 実験計画書 (
この二つを、git worktree 機能を使って同じディレクトリ階層にマウントします。これにより、AI エージェントは cd notes とするだけで、現在のコードブランチに関わらず、過去の全ての実験記録(思考履歴)にアクセスできるようになります。

再現性の完全性と時系列からの解放
このワークフローは、単にコードとノートを分けるだけでなく、科学的実験に不可欠な「再現性」と、探索的プロセスに必要な「柔軟性」を両立させます。
1. コミット ID による完全な再現
Note: DVC (Data Version Control) とは?
Git が「コード」の変更を記録するツールであるのに対し、DVC は「データ(巨大なファイル)」の変更を記録するツールです。 データの実体は S3 などのクラウドストレージに保存し、Git には「そのデータのハッシュ値(ID)」だけを
dvc.lockファイルとして記録します。 これにより、Git のコミット ID さえ確認できれば、その時点のコードだけでなく、その時点で使っていた学習データや生成されたモデルまで、完全に復元(dvc pull)することができます。
main ブランチにおける コミット ID (Git SHA) は、プロジェクトのあらゆる状態を再現するための唯一の真実として機能します。

- コードの再現: Git がソースコードのバージョンを保証します。
- 環境の再現:
uv.lockが依存ライブラリのバージョンを厳密に固定します。uvを使うことで、誰がどこで、実行しても同じ Python 環境が再現されます。 - データの再現:
dvc.lockがデータセットやモデル、中間生成物のハッシュ値を記録します。dvcはこれを元に、S3 などのストレージから正確なバージョンのデータをプルします。
この仕組みにより、過去の任意のコミット ID をチェックアウトし、uv sync と dvc pull を実行するだけで、当時の実験環境が完全に復元されます。
2. クリーンな実験実行と MLflow
Note: MLflow とは?
機械学習の実験管理ツールです。「いつ、誰が、どんなパラメータで実験し、どんな結果(精度)が出たか」を Web 画面で一覧表示できます。 本手法では、この MLflow の記録に「Git のコミット ID」を紐付けることで、実験結果から正確なコードとデータの状態を逆引きできるようにします。
再現性を担保するための基本的なステップを整理します。
git commit: コードと環境の状態を固定。make repro(dvc repro): 固定されたコードで実験を実行。- MLflow: 実験結果を MLflow に飛ばす。この際、現在の Git コミット IDが自動記録される。
dvc.lockcommit: 生成されたデータのハッシュ値を保存。
これにより、MLflow 上の「結果」から、Git コミット ID をたどり、その時使っていたデータ(DVC)と環境を再現するために必要な情報をほぼ漏れなくたどれるようになります。
3. 時空を超える思考履歴 (Orphan Branch)
一方で、思考履歴を管理する notes ブランチは、Orphan Branch(親を持たない孤立したブランチ) として存在します。これはコードのコミット(バージョン)に依存しません。
通常、Git で過去のコミットに戻ると、その当時のファイル状態に戻ってしまいます。しかし、git worktree でマウントされた notes ディレクトリは、コード側が過去 (switch --detach HEAD~10) に戻ろうが、現在 (switch main) に戻ろうが、常に「最新の思考履歴」を保持し続けます。
これにより、「過去の実験結果を参照しながら、新しい仮説を立てる」ことや、「複数の実験を行き来しながら、考察を一つのノートにまとめる」といった、時系列に縛られない柔軟な思考プロセスが可能になります。
Makefile による定型実行
この複雑なワークフローを人間(そして AI)が手動で行うのはミスの元です。そこで、セットアップから実験の開始・終了までを自動化する Makefile を作成しました。
Note: Makefile とは?
makeコマンドが読む「レシピ集」です。 ターミナルで毎回git switch -c exp/... mkdir -p notes/... uv run dvc repro git add dvc.lock git commit -m "..."のような長いコマンド列を手で打つ代わりに、
make start make repro make finishのような短いコマンドで同じ処理を実行できるようにする仕組みです。
- プロジェクトのルートディレクトリに
Makefileというファイル名で置くmake ターゲット名で、そのターゲットに対応する一連のコマンドが実行される
(この記事ではsetup,start,repro,finishがターゲット)つまり「実験の標準手順書をコード化したもの」が Makefile だと考えると理解しやすいでしょう。
これをプロジェクトのルートに配置するだけで、フローが完成します。

Makefile
# 変数
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
EXP_ID_FROM_BRANCH := $(shell echo $(BRANCH) | sed -e 's/^exp\///')
IS_EXP_BRANCH := $(filter exp/%,$(BRANCH))
NOTES_DIR := notes
EXP_NOTES_PATH := $(NOTES_DIR)/$(EXP_ID_FROM_BRANCH)
.PHONY: setup start repro finish
help:
@echo "AI-DS Workflow Commands:"
@echo " make setup - 思考履歴用のOrphanブランチを作成しWorktree展開"
@echo " make start - 実験ブランチ作成と計画書の初期化"
@echo " make repro - テストとDVC実行 (※事前にコミットが必要)"
@echo " make finish - 結果報告のコミットとメインへの統合"
# 1. セットアップ:Orphanブランチの作成とWorktreeマウント
setup:
@if [ -d "$(NOTES_DIR)" ]; then echo "Error: $(NOTES_DIR) already exists."; exit 1; fi
git switch --orphan notes
git rm -rf . || true
git commit --allow-empty -m "Initial commit for experiment notes"
git switch main
git worktree add $(NOTES_DIR) notes
@echo "Setup complete. 'notes/' is now linked to 'notes' branch."
# 2. 開始:コードブランチ作成 + 思考ブランチへの計画書追加
start:
ifneq ($(IS_EXP_BRANCH),)
@echo "Error: Cannot start experiment from an experiment branch."; exit 1
endif
@$(eval NEW_EXP_ID := $(shell date +%Y%m%d_%H%M%S))
@echo $(BRANCH) > $(NOTES_DIR)/$(NEW_EXP_ID)_source_branch
git switch -c exp/$(NEW_EXP_ID)
mkdir -p $(NOTES_DIR)/$(NEW_EXP_ID)
@printf "### 実験計画: $(NEW_EXP_ID)\n- 仮説:\n- 手法:\n" > $(NOTES_DIR)/$(NEW_EXP_ID)/spec.md
@mv $(NOTES_DIR)/$(NEW_EXP_ID)_source_branch $(NOTES_DIR)/$(NEW_EXP_ID)/source_branch.txt
@# 思考履歴側でのコミット
cd $(NOTES_DIR) && git add $(NEW_EXP_ID)/spec.md $(NEW_EXP_ID)/source_branch.txt && git commit -m "Plan: $(NEW_EXP_ID)"
@echo "Created branch exp/$(NEW_EXP_ID) and notes/$(NEW_EXP_ID)/spec.md"
# 3. 実験実行:コード側のコミット + DVC実行
repro:
ifeq ($(IS_EXP_BRANCH),)
@echo "Error: Not on an experiment branch."; exit 1
endif
@if [ -n "$$(git status --porcelain | grep -v '^?? notes/')" ]; then \
echo "Error: Uncommitted code changes found. Commit them first."; \
exit 1; \
fi
uv run pytest src/tests/
uv run dvc repro
git add dvc.lock
# .gitignore might be updated by dvc
git add .gitignore || true
git commit -m "[exp: $(EXP_ID_FROM_BRANCH)] dvc repro executed"
# 4. 終了:思考側のレポートコミット + コード側のマージ
finish:
ifeq ($(IS_EXP_BRANCH),)
@echo "Error: Not on an experiment branch."; exit 1
endif
@ls $(EXP_NOTES_PATH)/result.md > /dev/null 2>&1 || (echo "Error: result.md not found."; exit 1)
@# 思考履歴側でのレポートコミット
cd $(NOTES_DIR) && git add $(EXP_ID_FROM_BRANCH)/result.md && git commit -m "Result: $(EXP_ID_FROM_BRANCH)"
@$(eval PARENT_BRANCH := $(shell cat $(EXP_NOTES_PATH)/source_branch.txt 2>/dev/null || echo main))
git switch $(PARENT_BRANCH)
git merge exp/$(EXP_ID_FROM_BRANCH)
@echo "Merged experiment $(EXP_ID_FROM_BRANCH) into $(PARENT_BRANCH). Notes are safe in 'notes' branch."
Git worktree の魔法
この仕組みの肝は make setup にあります。
git switch --orphan notes git rm -rf . || true git commit --allow-empty -m "Initial commit..." git switch main git worktree add notes notes
通常、Git でブランチを切り替えるとディレクトリの中身が全て入れ替わります。しかし、git worktree add notes notes を実行すると、現在のディレクトリの中に notes/ というサブディレクトリができ、その中だけが notes ブランチの状態になります。
つまり、src/ などのコードを編集している main (または exp/*) ブランチにいながら、同時に notes/ 以下のファイル(別ブランチ)も参照・編集できるのです。これにより、AI は「ディレクトリ移動」というごく自然な操作で、コードと思考を行き来できるようになります。
Warning: 混ぜるな危険
もしあなたがプロジェクトのルートディレクトリで誤って
git switch notesを実行してしまうと、大量のファイルが「削除された」あるいは「未追跡」の状態として表示され、混乱するでしょう。これは、notesブランチがmainとは全く異なる歴史(Orphan Branch)を持つためです。この状態で誤って
git merge等をしてしまうと、コードの歴史と思考の歴史が混ざり合い、このワークフローの前提である「タイムラインの分離」が崩壊します。notesブランチは常にgit worktree経由(cd notes)でのみ操作することを心がけてください。
AI への指示書
この環境を AI に正しく認識させるために、以下のプロンプト(指示書)を .ai-instructions.md としてプロジェクトルートに置いておきます。Cursor、Claude Code、Antigravity などの AI コーディングエージェントにルールとして設定することで、彼らは自律的に実験サイクルを回し始めます。
.ai-instructions.md
# AI DS Protocol あなたは `ai-ds-worktree-flow` プロトコルに従うエージェントです。 ## 基本動作 1. プロジェクト開始時に `make setup` が済んでいるか確認せよ。 2. 実験開始は `make start`。作成された `notes/[ID]/spec.md` を埋め、ユーザーの「承認」を待て。 3. コードを書き終えたら `git commit`(`notes/` 以外の変更)を行い、その後 `make repro` を実行せよ。 4. 結果が出たら `notes/[ID]/result.md` を書き、承認を得てから `make finish` を実行せよ。 ## 注意点 - あなたが触るディレクトリは `src/`(コード)と `notes/`(記録)の 2 か所である。 - `notes/` 内の操作は `notes` ブランチに、それ以外は `exp/` ブランチに記録されることを理解せよ。
AI エージェントとの対話ログ(シミュレーション)
実際にこの環境で AI と協働すると、どのような体験になるのでしょうか。
私: 「昨日の実験、学習率 0.001 だと全然収束しなかったよね。別の手段を考えて。」
AI: 「はい、notes/20260216_xxx/result.md を確認しました。前回は損失がプラトーに達していましたね。学習率ではなく、バッチサイズを 2 倍にする実験を提案します。新しい実験ブランチを作成するために、make start を実行しますか?」
私: 「お願いします。」
(AI がコマンド実行: make start)
(出力: Created branch exp/20260217_120000 and notes/20260217_120000/spec.md)
AI: 「実験ブランチを作成し、計画書に『バッチサイズ倍増』の仮説を記述しました。実装に移ります。」
(AI がコード修正... git commit ... make repro)
AI: 「実験完了です。損失が順調に減少し、収束しました。notes/20260217_120000/result.md に結果を記録しました。」
私: 「よし、これでいこう。マージして。」
AI: 「make finish を実行します。」
(コードは main にマージされ、レポートは notes ブランチに保存される)
このように、AI はもはや単なる「コード生成ツール」ではなく、「実験のコンテキストを共有するパートナー」として振る舞うようになります。notes/ ディレクトリを見るだけで、過去にどんな実験をして、どんな結果だったのか(そしてそれはどのコードブランチでの出来事だったのか)を、AI 自身がいつでも振り返ることができるのです。
ぜひ、あなたのプロジェクトにも「AI のための記憶領域」を作ってみてください。

浦山 昌生 Masao Urayama
データ・AIソリューション本部 AIプロダクト統括部 AIプロダクトソリューション部 シニアデータアナリスト
AI ベンダーでデータサイエンティスト兼PL(プロジェクトリーダー)として機械学習モデルの開発やデータ分析の受託業務に従事。それまでは、ネットワークエンジニア、情報セキュリティエンジニアとして顧客の課題解決に対応。2021年10月にパーソルキャリアに入社し、推薦モデルの開発、情報検索システムの開発等、先進的なデータの活用を実践。
※2026年2月現在の情報です。