0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

git worktree で「レビューできる大きさ」を保っている話

0
Posted at

はじめに

AIにコードを書いてもらうようになって、困ったのは書いたコードの読む量でした。

「この機能を作って」と頼むと、DBもAPIも画面も、依存する先までまとめて作ってくれます。ありがたい反面、変更されるファイルが増えれば増えるほど、人の目でレビューするのが難しくなっていきました。

そこで今は、先に「レビューできる大きさ」で作業を区切っています。区切りごとにタスクを分けてissueを作り、git worktreeで作業フォルダも分けています。この記事では、worktreeの仕組みと、私が実際にやっている使い方をまとめます。

そもそもworktreeって何?

git worktreeは、1つのリポジトリから作業フォルダを何本も出せる機能です。

普通はリポジトリ1つに作業フォルダも1つで、別のブランチを見たいときはgit switchで中身を入れ替えます。worktreeを使うと、ブランチごとに別のフォルダを用意して、並べて開いておけます。

~/Documents/
├── myapp/              ← 本体
└── myapp-wt/
    ├── feature-db/     ← worktree(ブランチ feature/xxx-db)
    └── feature-api/    ← worktree(ブランチ feature/xxx-api)

ここで大事なのは、履歴は本体と共有していることです。cloneを何回もするのと違い、コミットもブランチも1か所にあるので、worktreeでコミットしたものは本体からもそのまま見えます。

使うコマンドはほぼこれだけです。

# リモートの最新のデフォルトブランチから、ブランチを切って別フォルダに出す
git fetch origin
git worktree add ../myapp-wt/feature-db -b feature/xxx-db origin/main

# 一覧
git worktree list

# 片付け
git worktree remove ../myapp-wt/feature-db

起点は、git fetchで取ってきたばかりのリモートのデフォルトブランチにしています(例ではorigin/main)。手元のブランチは、更新し忘れて古いことがあるからです。

なぜ使うのか:レビューが追いつかないから

きっかけは失敗でした。

ある機能をAIに作らせたとき、変更がまるごと1つのコミットに入ってしまいました。チケットは「管理画面」と「API」で分かれていて、「これは範囲外」とも書いてあったのに、ブランチとMRを1本で進めていたのが原因です。

次は反省して、機能を先に細かいチケットに分けてから、AIに順番に作らせました。このとき「コミットはしないで」とだけ伝えていて、チケットごとにどこへ置くかは決めていませんでした。その結果、すべてのチケットの変更が同じ作業フォルダに積み上がり、どの変更がどのチケットの分なのか分けて見られなくなりました。せっかく分けたのに、レビューする量は分ける前と変わりませんでした。

この2つで分かったのは、詰まるのは作る速さではなく受け取る速さだということです。分けるだけでなく、分けた単位ごとに置き場所(ブランチと作業フォルダ)まで分けておかないと、結局混ざります。

やること 目的
ブランチを分ける レビューできる量にする(こちらが本題)
worktreeで並べて進める 分けた単位を混ぜずに、同時に進める(補助)

「ブランチを分けるだけならgit switchでいいのでは」と思うかもしれません。ただ切り替えだと、次のような場面で困りました。

  • AIを2つ同時に動かすと、同じフォルダでは互いの変更が混ざる
  • 未コミットの変更が、切り替え先のブランチに持ち越されて混ざる
  • レビュー待ちのブランチを開いたまま、次の単位に進めない
  • 2つのブランチを同時に動かして見比べられない

私の使い方

1. 先に分けて、表にする

着手する前に、AIに分け方の案を出してもらいます。単位ごとに、ブランチ名と依存と、同時に進められるかを書かせます。DBから新しく作る機能なら、たとえばこんな表です。

単位 ブランチ 依存 進め方
①土台(DB・モデル) feature/xxx-db なし 先に単独で
②商品の登録画面 feature/xxx-products ① ③と同時に
③注文のAPI feature/xxx-api ① ②と同時に
④注文の管理画面 feature/xxx-admin ①③ 単独で

土台を作るかどうかは作業によって変わります。この例のようにDBから新しく作る機能なら、ほかの単位が乗るDBとモデルを土台として先に出します。土台という考え方が当てはまらない作業なら、土台は作らず、最初から機能ごとにブランチとMRを分けます。

土台を作るときは、それだけを先に単独で出します。そこだけに集中してレビューできますし、出した時点でDraft MRを作っておけば、出口が先にできます。

機能の単位は、フロント・バック・テストをひとまとまりにして切ると、レビューしやすくなります。大きさは、ファイル数よりも変更行数で見るのがよさそうです。ファイル数が少なくても、行数が多ければ分けたほうが読みやすくなります。

2. チケットや要件をもとにissueを作る

分けた単位ごとに、GitLab,Githabでissueを作ります。

これは普段タスク管理しているところでOK、Notion、Linear、Obsidianなど

元にするのは、チケットや要件です。
チケットには要望が2、3行しか書かれていないこともあるので、AIと問答しながら、完了の条件・壊しそうな箇所・まだ決まっていないことを詰めてからissueに起こします。

大きな機能なら親のissueを1つ作って、全体の順番と、取り合いになりそうなファイルを書きます。単位ごとのissueには「やること」と「やらないこと」を書きます。

ブランチとMRはissue 1つにつき1本です。AIにはissueの番号を渡して、本文とコメントを読んでから作らせます。指示を毎回会話に書かずに済み、何をどこまでやったかもあとからissueで追えます。

3. 同時に進めていい組だけworktreeに出す

同時に進める組だけ、worktreeを作ってそれぞれAIに渡します。1つのworktreeに1issue、1ブランチ、1MR、1セッションです。

マイグレーションと共通部品に触る単位は並べません。マイグレーションは同時に作ると実行順が入れ替わり、共通部品はほかの全部と衝突するからです。

4. 本数は作業に合わせて決める

同時に作らせる本数は、作業の重さとパソコンの余裕を見て決めます。2本のことが多いですが、3本並べることもあります。worktreeの中でテストまで動かすときは、そのworktree用の開発環境(Docker)も立てるので、その分メモリを使います。

気をつけているのは、レビュー待ちを溜めすぎないことです。作るほうが速いので、溜めると結局まとめて読むことになります。

5. 普段は本体のフォルダで作業する

worktreeはいつも使うわけではありません。普段は本体のフォルダで、最新のデフォルトブランチから切ったブランチで作業します。worktreeを出すのは、並行させたいときと、本体で別の作業をしている最中にレビュー用のブランチを開きたいときだけ。使い終わったら消します。

置き場所はリポジトリの外(myapp-wt/)にしています。

6. AIには担当をはっきり渡す

並べて動かして驚いたのは、AIが自分の担当を推測して、全員が同じ答えを出したことです。

当時はAIのセッションをすべて本体のフォルダで立ち上げていたので、今いる場所も、今のブランチも、未コミットの変更も全部同じに見えていました。そこから「自分の担当はどれか」を当てさせると、全員が同じチケットを名乗りました。今はworktreeごとにその中でAIを立ち上げ、どのworktreeで、どのブランチで、何をするかを最初の指示に必ず書いています。

AIの作業を回しやすくする道具

worktreeを何本も出してAIを並べると、どこで何が動いているのかが見えにくくなります。そこを補うために、次の道具を組み合わせています。

Orca

worktreeとAIのターミナルをまとめて扱えるアプリです。worktreeを作るとその作業場所のタブが開き、そこでClaude CodeやCodexを動かせます。どのworktreeでどのAIが動いているかが1画面で見えるので、並べても迷子になりません。

実装はClaude Code、レビューはCodexのように、タブごとに役割を分けることもあります。worktreeの作成・削除のときにスクリプトを呼べるので、worktreeを作ると開発環境の準備が、消すと片付けが、自動で走るようにしています。

ホワイトボード

Whiteboard Desktopというアプリに、AIが書いたコードの流れやレビューの結果を描かせています。入口から出口までの流れが枠でつながり、枠を押すとその行のコードが開きます。差分を頭から読む前に全体の形をつかめるので、レビューの入口として使っています。

このほか、よくやる作業はClaude Codeのスキル(AI向けの手順書)として自分で作っています。

使わない場面

何でもworktreeにすればいいわけではありません。次のようなときは使いません。

  • 1、2件の小さな修正。普通に1ブランチでやるほうが早い
  • 仕様が固まっていないとき。先に1本で試して、固まってから分ける
  • 依存が強くて、順番にしか進められないとき

おわりに

worktreeは「並行で速く作るための道具」として紹介されることが多いと思います。私にとっては並行して早く実装できるのもそうですが、レビューをしやすくするなどで使っています。
(まだ、人間の確認と修正が必要だと思うから)

本題はあくまで、レビューできる大きさに分けること。worktreeはそれを支える補助です。AIがいくらでも書いてくれるようになった今だからこそ、読む側の都合で区切る仕組みが要るのだと思っています。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?