Claude Media
Claude Codeのworktree作成がsymlinkで失敗する原因と外し方

Claude Codeのworktree作成がsymlinkで失敗する原因と外し方

Claude Codeの--worktreeが、symlinkになっているパスを理由にworktreeを作らないときの見分け方と外し方。3つのパス、v2.1.212より前との違い、Git LFSがpointerになる別の症状まで扱います。

claude --worktree がworktreeを作らずに止まり、エラーにシンボリックリンク(symlink)のパスが出ているなら、原因は3か所のどれかです。.claude、.claude/worktrees、そして作ろうとしているworktreeディレクトリ自体。このどれかがリンクだと、Claude Codeは作成を拒否します。

直し方は単純で、リンクを外して再実行するだけです。ただし .claude がリンクの場合は、外す前に中身の退避が要ります。この記事では見分け方から外し方、リンクを残したい場合の代替、似た症状として紛らわしいGit LFSの件までを扱います。

拒否されるのはどのパスか

Claude Codeがworktreeの作成を拒否するのは、次の3つのいずれかがシンボリックリンクのときです。エラーには、リンクだったパスが書かれます。worktreeは既定で .claude/worktrees/<name>/ の下に作られるため、この3つは作成の経路そのものにあたります。

パスリンクになりやすい構成の例
.claudeリンクになりやすい構成の例設定を別の場所で一元管理し、リポジトリ直下からリンクしている
.claude/worktreesリンクになりやすい構成の例worktreeの置き場だけ別ディスクに逃がしている
worktreeディレクトリ自体リンクになりやすい構成の例同名のリンクが .claude/worktrees/<name> に残っている

注意したいのは、対象が「リポジトリの中にコミットされたリンク」に限られないことです。手元で張ったリンクでも、CLAUDE.mdや設定を共有するために張ったリンクでも、この3か所に当たれば同じ扱いになります。

v2.1.212でリンクを辿らなくなった理由

v2.1.212より前は、リポジトリにこの3か所のいずれかへのリンクがコミットされていると、worktreeの作成はリンクをそのまま辿りました。その結果、リポジトリの外にファイルが作られる可能性がありました。

現在は、リンクを辿らずに作成を止めます。リンクを辿って外へ書く経路が塞がれ、書き込み先はリポジトリの内側に収まります。

古いバージョンで動いていた構成が、更新後に急に失敗し始めた場合は、この変更が原因の可能性があります。手元のバージョンは次で確認できます。

claude --version

どのパスがリンクかを調べる

エラーが指すパスをそのまま信じてよいのですが、複数が重なっていることもあります。リポジトリのルートで3か所を続けて確認しておくと、外し忘れが起きません。

# リンクなら先頭が l で、-> の後に実体が出る
ls -ld .claude .claude/worktrees .claude/worktrees/*
 
# リンクかどうかだけを真偽で見たいとき
test -L .claude && echo ".claude はリンク"
test -L .claude/worktrees && echo "worktrees はリンク"

ls -ld の出力で、行頭が l なら、その行はシンボリックリンクです。矢印の右側が実体の場所です。.claude/worktrees/* は、過去のセッションが残したディレクトリやリンクを拾うために入れています。

Claude Codeに調べさせる手もあります。「--worktree がsymlinkを理由に失敗した。.claude、.claude/worktrees、.claude/worktrees/* を ls -ld で確認して、リンクのものを列挙して」と頼めば、コマンドを実行して出力を読んでくれます。外す作業は、実体の場所を見てから自分で判断するのが安全です。

リンクを外して作成し直す

外し方はパスごとに違います。共通する注意点は、消す対象をリンクそのものに絞ることです。実体のディレクトリを消してしまうと、リンク先にあった内容が失われます。

worktreeディレクトリ自体がリンクのとき

過去のセッションが残したリンクなら、リンクだけを消せば済みます。

rm .claude/worktrees/feature-auth
claude --worktree feature-auth

.claude/worktreesがリンクのとき

置き場を別ディスクに逃がしていた構成です。リンクを外して実ディレクトリに戻すと、既存のworktreeはリンク先に取り残されます。残したい作業があれば、先に git worktree list で場所を確かめ、コミットかブランチへの退避を済ませてください。

git worktree list
rm .claude/worktrees
mkdir .claude/worktrees

.claude/worktrees/ を .gitignore に入れておく運用は、実ディレクトリに戻したあとも変わりません。worktreeの中身がメインチェックアウトで未追跡ファイルとして見えるのを防げます。

.claudeがリンクのとき

いちばん影響が大きいケースです。.claude の中にはsettings.json、skills、agentsなどが入っているため、リンクを外すとそれらがリポジトリから見えなくなります。

  • リンク先の中身を、リポジトリ直下の実ディレクトリ .claude へコピーする
  • コピー後にリンクを消し、コピーした内容が読み込まれることを確認する
  • 共有元と二重管理になるので、どちらを正とするか決めておく

.claude/skills をgitignoreしている構成では、worktree側に .claude/skills がなければ、メインチェックアウトのプロジェクトスキルが読み込まれます。agentsとcommandsも同じです。スキルについてはv2.1.277以降が条件です。worktreeで .claude の一部だけ使えればよいなら、リンクを外したあとの手当ては小さく済みます。

リンクを残したまま作成を通したい場合は、次の節の選択肢で回避します。

リンクを残したいときの選択肢

worktreeを作る場所や作り方を変えたいだけなら、リンクを使わずに済む手段があります。

WorktreeCreate hookを使うと、worktreeの作成そのものをスクリプトに置き換えられます。作る場所を .claude/worktrees 以外にでき、hookの書き方は別記事にまとめています。hookが作るディレクトリは、リポジトリの外に置く必要があります。リポジトリの内側に作ると、別の拒否に当たります(後述)。

大きなディレクトリを共有したい場合は、worktree.symlinkDirectories が用意されています。node_modules のようなディレクトリを、worktreeの中へリンクとして張る設定です。

{
  "worktree": {
    "symlinkDirectories": ["node_modules"]
  }
}

これはworktreeの内側にリンクを作る設定で、作成前に拒否される3つのパスとは別の話です。設定の詳細はworktree.symlinkDirectoriesの解説を参照してください。

症状が似ているもう1つの問題: Git LFSのファイルがpointerになる

worktreeは作られたのに、LFSで管理しているファイルが数行のテキストになっている場合は、リンクとは別の問題です。

git lfs install --local でLFSを設定していると、Claude Codeが作ったworktreeには、実体ではなくLFSのpointer(参照情報だけのテキスト)ファイルが入ります。--local はLFSのフィルターをリポジトリ自身の .git/config に書き込みます。フィルターはシェルコマンドなので、リポジトリに書き込める者、つまりClaude自身も含めて誰かが仕込める可能性があります。Claude Codeは、そのため作成時にリポジトリ固有のフィルタードライバーを実行しません。v2.1.247より前は実行していました。

素の git lfs install はグローバル設定に書くので、この影響を受けません。リポジトリ固有の設定に定義した他のフィルタードライバーも、同じ扱いです。

実体を取り戻すには、worktreeの中で次を実行します。

git lfs pull

worktreeがまったく作られない4つのエラー

フィルタードライバーの定義を安全に扱えないときは、pointerファイルどころかworktreeが作られません。エラー文に応じて、対処は次のとおりです。

エラー文の一部対処
Could not read the repository git config to neutralize filter drivers対処.git/config の読み取り権限などを直して再実行する
...a filter driver whose name cannot be neutralized (contains "=" or a newline)対処該当のフィルタードライバー名を .git/config で変更または削除する
The repository git config has a conditional include (includeIf)対処includeIf が読み込む設定を .git/config に直接書き、includeIf を消す
Git was not run: the repository's own git config sets <key>対処エラーが示すキーを、自分の設定ならグローバル設定へ移す。心当たりがなければ削除する

includeIf は、グローバルのgit設定にあっても引っかかりません。リポジトリ自身の .git/config にあるときだけが対象です。最後の行で示されるキーは、lfs.customtransfer.<name>.path や lfs.standalonetransferagent のように、Git LFSに外部プログラムを指定するものです。

作成後に拒否される別のエラーとの見分け方

エラーが Refusing to use <path> as an isolation worktree で始まる場合は、この記事の症状ではありません。こちらは、作った(または既存の)ディレクトリのgit上の素性を確かめ、メインチェックアウトに解決されてしまうと判断したときの拒否です。

この2つは、原因も対処も違います。

観点今回の症状Refusing to use
拒否のタイミング今回の症状worktreeを作る前Refusing to use作成後、採用する前
見ているもの今回の症状3つのパスがリンクかどうかRefusing to useディレクトリのgitメタデータの行き先
基本の対処今回の症状リンクを外して再実行Refusing to useメッセージの末尾が示す復旧手順に従う

後者のメッセージには、worktreeのパスの中にシンボリックリンクがあることが原因として名指しされる場合もあります。公式は、素性を確認できなかったディレクトリを消す前に、まず原因(パス中のシンボリックリンクやgit自体の失敗)を先に直すよう述べています。ディレクトリは無事なことがあるためです。後者の詳しい動きは、worktreeがmainへの読み取り専用gitも拒否する仕様の記事にも関連があります。

再発を避けるための確認手順

リンクを外したあとに、同じ失敗を繰り返さないための確認です。

  1. ls -ld .claude .claude/worktrees で、どちらも d から始まる実ディレクトリになっている
  2. claude --worktree <name> を実行して、.claude/worktrees/<name>/ が作られる
  3. 作成後に git worktree list で、そのworktreeが登録されている
  4. LFSを使うリポジトリでは、worktree内でファイルの中身がpointerでないか確認する

3点目は、掃除の話にもつながります。worktreeが溜まってきたら、.claude/worktreesの掃除の手順を参照してください。worktree機能の全体像はWorktree実践ガイドにあります。

まとめ

失敗の原因がsymlinkなら、.claude、.claude/worktrees、worktreeディレクトリの3か所を ls -ld で確かめ、リンクを外せば直ります。.claude がリンクの場合だけは、中身を実ディレクトリへ移してからにしてください。 worktreeの場所を変えたいなら WorktreeCreate hook、大きなディレクトリを共有したいなら worktree.symlinkDirectories が、リンクを避ける現実的な選択肢です。LFSのファイルがpointerになる件は、git lfs pull で取り戻せます。

この記事を共有:XはてブLinkedIn