Claude Code worktree が古い基点になる問題

2026/6/26

代表

Claude Code の worktree 機能は、並行作業を手早く始められる便利な仕組みです。一方で、新しい worktree が「最新の既定ブランチ」ではなく古いコミットから作られ、気づかないうちに古いコードの上で作業してしまう場合があります。この記事では、その発生条件と確認方法、そして git fetch を作業フローに組み込む対処法を、私たちの検証結果とあわせて整理します。

なお本記事では分かりやすさのため、既定ブランチの例として main を用いて説明します。正確には基点はリポジトリの既定ブランチ(origin/HEAD)であり、masterdevelop を運用している場合も同様に当てはまります。

TL;DR

  • Claude Code の --worktree-w)は、ローカルにキャッシュされたリモートの既定ブランチの追跡参照(refs/remotes/origin/HEAD、多くのリポジトリでは origin/main)を基点に worktree を作ります
  • このキャッシュは前回 git fetch した時点のもので、リモートが先に進んでいると古い基点から枝分かれします
  • 私たちの検証環境(Claude Code 2.1.193)では、worktree 作成時にネットワーク経由の git fetch は実行されませんでした
  • 対処は 2 通りです。手軽さなら SessionStart フックで git fetch、確実さなら WorktreeCreate フックで作成処理ごと差し替えます

何が起きるのか

症状

並行作業のために新しい worktree を作ったところ、その作業ブランチが最新の既定ブランチではなく数コミット前から枝分かれしていた、というケースです。そのまま Pull Request を作ると、初手からコンフリクトが出たり、すでにマージ済みの変更を含まない古い状態で開発を進めてしまったりします。

再現の条件

次の条件が重なると発生します。

  • 同僚がリモートの既定ブランチ(例: main)に複数の変更をマージした
  • 手元で git fetch がしばらく走っておらず、ローカルの追跡参照(例: origin/main)が古い
  • その状態で claude -w を実行し、古い追跡参照を基点に worktree が作られる

なぜ古い基点になるのか

基点は「ローカルのリモート追跡参照」

ここで重要なのは、worktree のベースが次の 3 つのうちどれか、という点です。既定ブランチが main のリポジトリを例にすると、次のようになります。

  • 実際のリモートの既定ブランチ(GitHub 上の main): 参照しない
  • refs/heads/main(ローカルの既定ブランチ): これでもない
  • refs/remotes/origin/main(リモート追跡参照): これが使われる

refs/remotes/origin/main は、前回 git fetch した時点のリモートの状態を保存したローカルのキャッシュです。fetch を挟まないかぎり、この値はリモートの最新と一致するとはかぎりません。なお、既定ブランチが master などの場合は、それぞれ refs/heads/masterrefs/remotes/origin/master に読み替えてください。Claude Code はリポジトリの既定ブランチ(origin/HEAD)を基点として解決します。

公式ドキュメントの記述と実際の挙動

Claude Code の公式ドキュメントでは、worktree は既定でリポジトリの既定ブランチ origin/HEAD から分岐し、リモートに一致したクリーンな状態で始まる、と説明されています(基点に関する設定 worktree.baseRef"fresh""head" の 2 値のみを取ります)。

一方、私たちが Claude Code 2.1.193 で検証したところ、worktree 作成時にネットワーク経由の git fetch は実行されず、ローカルにキャッシュ済みの追跡参照がそのまま基点に使われました。具体的には、ローカルの追跡参照(origin/main)を意図的に古いコミットへ巻き戻した状態で claude -w を実行すると、新しい worktree は最新のリモート先端ではなく、その古いコミットの上に作られました。この挙動はバージョンや環境によって異なる可能性があるため、利用中のバージョンでの確認をおすすめします。

公式リポジトリでも報告されている

この挙動は、Claude Code の公式リポジトリでも Issue #28958「Worktree creation should sync from remote default branch, not local」 として報告されています。「worktree 作成はローカルではなくリモートの既定ブランチから同期すべき」という趣旨の機能要望で、本記事執筆時点では Open(未解決)の状態です。

古い基点で作られていないか確認する

worktree のブランチがどのコミットから作られたかは、Git で確認できます。

# worktree のブランチが何を基点に作られたかを確認
git reflog show <branch> | tail -1
# 例: <sha> branch: Created from origin/main

# 既定ブランチを特定する
git symbolic-ref refs/remotes/origin/HEAD
# 例: refs/remotes/origin/main

# ローカルの追跡参照と実際のリモートの差を確認(main は既定ブランチに読み替え)
git fetch origin
git log --oneline origin/main -3

Created from origin/main と記録されていても、その <sha> が古ければ、キャッシュされた古い参照から作られたことを意味します。

対処法

基本方針は「worktree が作られる前に git fetch を済ませ、ローカルの追跡参照を最新化しておく」ことです。Claude Code のフック機能を使う 2 通りを紹介します。

方法 1: SessionStart フックで git fetch(手軽)

セッション開始時に毎回 git fetch を走らせる方法です。settings.json に次を追記します。

{
  "hooks": {
    "SessionStart": [
      { "matcher": "", "hooks": [
        { "type": "command",
          "command": "git rev-parse --is-inside-work-tree >/dev/null 2>&1 && git remote get-url origin >/dev/null 2>&1 && git fetch origin --prune 2>/dev/null || true" }
      ] }
    ]
  }
}
  • セッション開始のたびにローカルの追跡参照が最新化されます
  • Git 管理下かつ origin がある場合だけ動作し、それ以外では何もしないため、Git 管理外のディレクトリで起動してもエラーになりません
  • 注意点として、このフックはセッション開始時に走るため、作られたばかりの worktree の基点を後からさかのぼって直すわけではありません。次回以降の作成を新鮮に保つこと、そして現在のセッションでも最新の追跡参照を手元にそろえ、git rebase で追従しやすくすること、という位置づけです

方法 2: WorktreeCreate フックで作成処理を差し替える(確実)

作成のたびに、その場で fetch してから最新の基点で作ることを確実にしたい場合は、WorktreeCreate フックを使います。このフックは Claude Code 既定の worktree 作成処理を置き換えるため、フック側で「fetch する、worktree を作る、作成したパスを返す」までを担います。次の例は、既定ブランチ(origin/HEAD)を自動で解決して基点にします。

#!/bin/sh
# stdin(JSON) で {name, cwd, ...} が渡る。
# 成功時は、作成した worktree の絶対パスを stdout に 1 行だけ出力する。
set -eu
input=$(cat)
name=$(printf '%s' "$input" | python3 -c 'import json,sys;print(json.load(sys.stdin)["name"])')
repo=$(printf '%s' "$input" | python3 -c 'import json,sys;print(json.load(sys.stdin)["cwd"])')
path="$repo/.claude/worktrees/$name"
branch="worktree-$name"
{
  git -C "$repo" fetch --prune origin || echo "warn: fetch に失敗。キャッシュした参照を使います" >&2
  # 既定ブランチを解決(origin/HEAD)。取得できなければ origin/main にフォールバック
  base=$(git -C "$repo" symbolic-ref --quiet refs/remotes/origin/HEAD 2>/dev/null || echo refs/remotes/origin/main)
  base=${base#refs/remotes/}
  git -C "$repo" worktree add -b "$branch" "$path" "$base"
} >&2
printf '%s\n' "$path"

設定側は次のとおりです。

{ "hooks": { "WorktreeCreate": [ { "hooks": [
  { "type": "command", "command": "/path/to/worktree-create.sh", "timeout": 60 }
] } ] } }
  • 作成時に fetch してから最新の基点でブランチを切るため、基点の鮮度を作成時点で担保できます
  • 既定の作成処理を置き換える点に注意が必要です。.worktreeinclude(Git 管理外ファイルの自動コピー)を使っている場合は、その処理もフック内で再現する必要があります

どちらを選ぶか

観点SessionStartWorktreeCreate
設定の手軽さ高い(1 行)中(作成処理を実装)
現在の worktree の基点を最新化間接的直接(作成時に最新化)
既定の作成挙動への影響なし置き換える

手軽に始めるなら方法 1、基点の鮮度を作成時点で担保したいなら方法 2、という使い分けになります。

まとめ

  • Claude Code の worktree は、ローカルにキャッシュされたリモートの既定ブランチの追跡参照を基点に作られるため、fetch を挟まないと古い状態から枝分かれする場合があります
  • 私たちの検証では、作成時に自動の fetch は行われませんでした(バージョンによって異なる可能性があります)
  • 対処は、セッション開始時に fetch する手軽な方法と、作成処理ごと差し替えて作成時に fetch する確実な方法の 2 通りです
  • 並行作業を多用するチームほど、フックで fetch を仕組み化しておくと、初手のコンフリクトや手戻りを減らせます

私たちつくばAIラボでは、AI 開発ツールの運用設計や DX 推進のご相談を承っています。

出典

© 2026 つくばAIラボ株式会社