MCPcopy
hub / github.com/claude-code-best/claude-code / getOrCreateWorktree

Function getOrCreateWorktree

src/utils/worktree.ts:235–375  ·  view source on GitHub ↗

* Creates a new git worktree for the given slug, or resumes it if it already exists. * Named worktrees reuse the same path across invocations, so the existence check * prevents unconditionally running `git fetch` (which can hang waiting for credentials) * on every resume.

(
  repoRoot: string,
  slug: string,
  options?: { prNumber?: number },
)

Source from the content-addressed store, hash-verified

233 * on every resume.
234 */
235async function getOrCreateWorktree(
236 repoRoot: string,
237 slug: string,
238 options?: { prNumber?: number },
239): Promise<WorktreeCreateResult> {
240 const worktreePath = worktreePathFor(repoRoot, slug)
241 const worktreeBranch = worktreeBranchName(slug)
242
243 // Fast resume path: if the worktree already exists skip fetch and creation.
244 // Read the .git pointer file directly (no subprocess, no upward walk) — a
245 // subprocess `rev-parse HEAD` burns ~15ms on spawn overhead even for a 2ms
246 // task, and the await yield lets background spawnSyncs pile on (seen at 55ms).
247 const existingHead = await readWorktreeHeadSha(worktreePath)
248 if (existingHead) {
249 return {
250 worktreePath,
251 worktreeBranch,
252 headCommit: existingHead,
253 existed: true,
254 }
255 }
256
257 // New worktree: fetch base branch then add
258 await mkdir(worktreesDir(repoRoot), { recursive: true })
259
260 const fetchEnv = { ...process.env, ...GIT_NO_PROMPT_ENV }
261
262 let baseBranch: string
263 let baseSha: string | null = null
264 if (options?.prNumber) {
265 const { code: prFetchCode, stderr: prFetchStderr } =
266 await execFileNoThrowWithCwd(
267 gitExe(),
268 ['fetch', 'origin', `pull/${options.prNumber}/head`],
269 { cwd: repoRoot, stdin: 'ignore', env: fetchEnv },
270 )
271 if (prFetchCode !== 0) {
272 throw new Error(
273 `Failed to fetch PR #${options.prNumber}: ${prFetchStderr.trim() || 'PR may not exist or the repository may not have a remote named "origin"'}`,
274 )
275 }
276 baseBranch = 'FETCH_HEAD'
277 } else {
278 // If origin/<branch> already exists locally, skip fetch. In large repos
279 // (210k files, 16M objects) fetch burns ~6-8s on a local commit-graph
280 // scan before even hitting the network. A slightly stale base is fine —
281 // the user can pull in the worktree if they want latest.
282 // resolveRef reads the loose/packed ref directly; when it succeeds we
283 // already have the SHA, so the later rev-parse is skipped entirely.
284 const [defaultBranch, gitDir] = await Promise.all([
285 getDefaultBranch(),
286 resolveGitDir(repoRoot),
287 ])
288 const originRef = `origin/${defaultBranch}`
289 const originSha = gitDir
290 ? await resolveRef(gitDir, `refs/remotes/origin/${defaultBranch}`)
291 : null
292 if (originSha) {

Callers 3

createWorktreeForSessionFunction · 0.85
createAgentWorktreeFunction · 0.85
execIntoTmuxWorktreeFunction · 0.85

Calls 12

worktreePathForFunction · 0.85
worktreeBranchNameFunction · 0.85
readWorktreeHeadShaFunction · 0.85
mkdirFunction · 0.85
worktreesDirFunction · 0.85
execFileNoThrowWithCwdFunction · 0.85
getDefaultBranchFunction · 0.85
resolveGitDirFunction · 0.85
resolveRefFunction · 0.85
tearDownFunction · 0.85
getInitialSettingsFunction · 0.50
pushMethod · 0.45

Tested by

no test coverage detected