5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Claude Code に作業を投げている間の待ち時間、けっこう長いですよね。その間に別の作業も進めたくなったので、git worktree(作業ディレクトリを分ける機能)を使った並列開発を試してみました。

やってみたら思ったより簡単で、「worktree を作って、そのディレクトリを VS Code で開き直す」だけで並列作業の環境が整いました

この記事では、その手順をメインに紹介します。あわせて、途中で知った worktree の注意点と、自分が Dev Container で開いているおかげで助かっている話も書いておきます。

なぜ worktree を使うのか

普通に1つの作業ディレクトリで複数ブランチを扱おうとすると、git checkout でブランチを切り替えるたびに作業中の変更を退避することになって面倒ですよね。しかも、Claude Code に何かを任せている最中に別ブランチへ切り替えると、その作業ごと巻き込まれてしまいます。

そこで、git worktree を使うと、同じリポジトリの別ブランチを別ディレクトリとして同時に展開できます。片方の Claude Code に機能追加をさせつつ、もう片方の Claude Code で別の機能を進める、みたいな並列作業ができるわけです。どちらも同じ .git を共有しているので、commit も merge も diff も普通どおりにできます。

やり方その1、Claude Code に作ってもらう

Claude Code は git worktree をネイティブにサポートしています。一番簡単なのは起動時に --worktree(省略形は -w)を付ける方法です。

claude --worktree feature-login

これだけで、リポジトリルートの .claude/worktrees/feature-login/ に worktree ができて、その中でセッションが始まります。元のディレクトリは汚れません。名前を省略すると、Claude が bright-running-fox のような名前を勝手に付けてくれます。

claude --worktree

別のターミナルでもう一度、別の名前で起動すれば、2つ目の並列セッションになります。

claude --worktree feature-search

起動中の Claude Code に「worktree で作業して」と指示しても作ってくれます。その場合は .claude/worktrees/agent-xxxxxxxx のような名前のディレクトリができます。自分の手元はこんな状態になっていました

$ git worktree list
/Users/me/work/myapp                                        816bae4 [dev]
/Users/me/work/myapp/.claude/worktrees/agent-xxxxxxxx       54c8bab [wip/feature-login]

本体は dev のまま、別ディレクトリに wip/feature-login が展開されています。Claude Code が並列作業用に worktree を切ってくれた状態です。

やり方その2、git で手動で作る

場所やブランチを自分で決めたいときは、git を直接叩くほうが確実です。

git worktree add ../myapp-feature-login -b feature-login

これで ../myapp-feature-loginfeature-login ブランチの作業ディレクトリができます。

作ったら VS Code で開き直す

ここが自分のやり方の肝なんですが、並列処理をしたくて worktree を作ったら、そのディレクトリを VS Code で開き直します。worktree はただのディレクトリなので、開けばその中で普通に編集も差分確認もできます。

code .claude/worktrees/agent-xxxxxxxx

本体のウィンドウはそのまま残しておいて、worktree のウィンドウを別に開けば、2つのブランチを2枚のウィンドウで並べて作業できます。CUI の git worktree list だけだと状態がわかりにくいので、ウィンドウを分けておくと頭の中も整理しやすいです。

ちなみに自分は Dev Container でプロジェクトを開いているので、worktree のディレクトリを開き直すと、そのまま worktree 基準でコンテナの中に入る形になります。これが後で出てくるリスクの話とつながってきます。

ハマりやすいポイント

実際に触ってみて、ここは気をつけたほうがいいなと思った点が2つありました。

ひとつ目は、ベースブランチの挙動です。Claude Code の worktree はデフォルトでリモートの origin/HEAD から枝分かれするので、今いるブランチの未コミットの変更は引き継がれません。今の作業の続きから分岐したいときは、設定で worktree.baseRefhead にします。

{
  "worktree": {
    "baseRef": "head"
  }
}

実際に手元で試してみたところ、デフォルト(fresh)だと worktree は origin/HEAD のコミットから始まって、本体の未コミット変更は持ってきませんでした。一方 baseRefhead にすると、現在の HEAD から分岐するのに加えて、本体側の未コミット変更(追跡ファイルの変更)まで worktree 側に引き継がれました。本体の diff と完全に一致していたので、文字どおり「今の作業の続き」から始められるという挙動です。作業中のものごと持っていきたいときは head が便利ですね。

ふたつ目は、git 管理外のファイルがコピーされないことです。worktree は新しいチェックアウトなので、.envnode_modules はついてきません。「同じに見えるのに動かない」というのはだいたいこれが原因です。ここでハマりました…。

これに対して Claude Code には .worktreeinclude という機能があります。プロジェクトルートに .gitignore と同じ書式で書いておくと、指定した管理外ファイルを worktree 作成時にコピーしてくれる、というものです。

.env
.env.local
config/secrets.json

ただ、ここは自分の環境で試したときに引っかかった点があります。起動中の Claude にセッション内で worktree を作らせる経路(.claude/worktrees/agent-xxxxxxxx ができるやつ)だと、.worktreeinclude に書いたファイルがコピーされませんでした。どうやらこの機能は claude --worktree の CLI 起動経路向けのようで、セッション内で作る経路では効かない可能性があります。自分のように VS Code 上で Claude に worktree を作らせるスタイルの場合は、.worktreeinclude に頼り切らず、worktree 側で .env を手当てする前提でいたほうが安全そうです。

node_modules のような重いものは、どのみちコピーより worktree 側で npm install し直すほうが現実的でした。

あと、.claude/worktrees/.gitignore に入れておくのも大事です。これをやらないと、本体側で git status したときに worktree の中身がゴミとして見えてしまいます。

注意点、worktree はサンドボックスじゃない

並列開発に便利な worktree ですが、調べている途中で気になる記事を見つけました(Claude Code が Git Worktree をめちゃくちゃに壊した話)。

ポイントはこうです。worktree は git の作業ディレクトリを分ける仕組みであって、プロセスを隔離するサンドボックスではない、ということ。ディレクトリは分かれていても、そこで動くプロセスは普通のファイル権限を持っているので、親ディレクトリや隣の worktree にもアクセスできてしまいます。

記事の再現例がわかりやすかったです。ビルドスクリプトの中に、出力先が親方向を指す相対パスで書かれていたんですね。

mkdir -p ../repo/published
echo "..." > ../repo/published/index.html

Claude Code は別の worktree の中で起動されていたのに、README どおりにこのスクリプトを実行した結果、../repo つまり本体側のファイルを上書きしてしまった、という話です。記事によると、この現象は Opus、Sonnet、Haiku の全モデルで起きたそうです(2026年6月16日時点)。

怖いのは、Claude が悪さをしたわけじゃない点です。ユーザーの指示に従って README を読んで、書かれた手順を素直に実行しただけなんですよね。人間なら「このスクリプト、外に書き込むぞ?」と気づけたかもしれない相対パスでも、エージェントはそのまま実行してしまう。worktree で分かれているという見た目の安心感が、逆に油断を生むわけです。

念のため自分の手元でも確かめてみました。テスト用の worktree を作って、その中から相対パスで本体側のディレクトリに書き込んでみたところ、あっさり成功してしまいました。本体側にちゃんとファイルが現れます。worktree はファイルシステムを隔離していない、というのは記事のとおりです。ひとつ補足すると、Claude Code が作る worktree は本体リポジトリの中(.claude/worktrees/<名前>/)に置かれるので、本体ルートに届く相対パスは記事の例(../repo)とは段数が変わります。配置によって ../ の数は変わりますが、「外に書ける」という結論は同じでした。

Dev Container で開いていると、ここが助かる

ここで最初の「worktree を VS Code で開き直す」という話に戻ります。

自分は Dev Container でプロジェクトを開いているので、worktree のディレクトリを開き直すと、そのコンテナの中で Claude Code が動きます。コンテナの中からは、ホスト側のファイルシステムにはマウントした範囲しか見えません。

つまり、さっきの記事のような「相対パスで worktree の外に書き込んでしまう」事故が起きても、コンテナの境界で止まってくれるはず、という期待があります。worktree 自体は隔離してくれないけれど、Dev Container というレイヤーがその外側の防波堤になってくれる、というイメージですね。

ただ、ここは正直まだコンテナ内できっちり検証できていません(越境書き込みのテストはホスト直の環境でやったものです)。コンテナの中から同じことを試して、本当にホスト側に漏れないかは、近いうちに確かめようと思っています。それに、効くかどうかはマウント設定次第でもあります。ホスト側を広めにマウントしていれば素通りしてしまうので、worktree ごとにコンテナを開くなら、マウント範囲はそのプロジェクトに絞っておくのがよさそうです。

それでもやっておきたいこと

Dev Container があるとはいえ、念のためこれはやっておこうと思いました。

worktree で作業させる前に本体ブランチを必ずコミットかプッシュしておくこと。事故っても戻せる状態を作っておくのが先決です。記事の事故も、本体が git restore . で戻せたのは未コミットだったからで、コミット済みならもっと厄介でした。

あとは、worktree 側で走る build や test のスクリプトに ../ で外へ出ていく書き込みがないか先に見ておくこと、--dangerously-skip-permissions(権限確認をスキップするフラグ)を自律実行で安易に使わないこと、このあたりですね。

まとめ

並列開発のために worktree を作って、そのディレクトリを VS Code で開き直す。やってみると手順はこれだけで、待ち時間を別の作業で埋められるのはかなり快適でした。

一方で、worktree は隔離の仕組みではないというのは頭に置いておいたほうがよさそうです。これは実際に手元で、worktree の中から本体側に書き込めることを確かめました。ディレクトリが分かれていても、そこで動くプロセスは外のファイルを触れてしまいます。自分の場合は Dev Container で開いているので、コンテナが防波堤になってくれることを期待していますが、ここはまだ検証しきれていないので過信は禁物です。そうでない環境なら、本体をこまめにコミットしたりスクリプトの中身を確認したりといった備えがいると思います。

しばらくはこの「worktree + Dev Container で開き直す」スタイルで並列開発を続けてみようと思います。

参考リンク

5
1
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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?