{"record":{"id":"3fa710453667ca9f","repo":"gitbutlerapp/gitbutler","slug":"worktrees","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/worktrees.rs","lineNumber":148,"sourceCode":"        .and_then(|worktree| worktree.id().map(ToOwned::to_owned))\n        .context(\"git registered the new checkout as a linked worktree\")\n}\n\nfn git_worktree(repo: &gix::Repository, subcommand: &str, args: &[&OsStr]) -> anyhow::Result<()> {\n    let mut cmd = std::process::Command::new(gix::path::env::exe_invocation());\n    // These would override `-C`.\n    for var in [\"GIT_DIR\", \"GIT_WORK_TREE\", \"GIT_INDEX_FILE\"] {\n        cmd.env_remove(var);\n    }\n    let output = cmd\n        .arg(\"-C\")\n        .arg(repo.workdir().unwrap_or(repo.common_dir()))\n        .args([\"worktree\", subcommand])\n        .args(args)\n        .output()\n        .with_context(|| format!(\"Failed to run `git worktree {subcommand}`\"))?;\n    if !output.status.success() {\n        anyhow::bail!(\"{}\", String::from_utf8_lossy(&output.stderr).trim());\n    }\n    Ok(())\n}\n\n/// The outcome of [`move_uncommitted_changes()`].\n#[derive(Debug, Clone, Copy)]\npub struct MoveUncommittedChangesOutcome {\n    /// Conflict markers were written into `main_repo`'s working directory and index.\n    pub conflict_occurred: bool,\n}\n\n/// Move some or all of the uncommitted changes of the linked worktree `worktree_repo` into the\n/// uncommitted changes of `main_repo`.\n///\n/// `worktree_repo` must share `main_repo`'s object database and have no object memory, as\n/// returned by [`open_worktree_repo()`] - the same requirement `ChangeSource::Worktree`\n/// (`crate::commit`) has, since this writes loose objects through it that `main_repo` must see\n/// immediately.","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-workspace/src/worktrees.rs#L130-L166","documentation":"This helper shells out to `git worktree <subcommand>` and, when git exits non-zero, surfaces git's captured stderr verbatim as the error. It is a transparent pass-through of any `git worktree add/remove/...` failure, wrapped only by the 'Failed to run `git worktree <subcommand>`' context on spawn failure.","triggerScenarios":"Any underlying git failure from the add or remove wrappers: branch already checked out in another worktree, path exists or is not writable, worktree not registered, dirty/locked worktree on remove, invalid ref, or a missing/broken git binary.","commonSituations":"Adding a worktree for a branch that is already checked out elsewhere ('fatal: ... is already used by worktree ...'); removing a worktree with a lock file; run from an environment where git is not on PATH (the context message 'Failed to run...' variant); paths with characters git rejects.","solutions":["Read the message body — it is git's own stderr — and fix the underlying git issue it names","For 'already used by worktree', remove/prune the other worktree or use a different branch (or `git worktree add --detach`)","For removal failures, `git worktree unlock <path>` first or force removal","Verify git is installed and on PATH if the failure is the spawn-context variant"],"exampleFix":"// handle git's stderr surface explicitly\nmatch add(&repo, &path, branch, base) {\n    Ok(short) => ...,\n    Err(e) if e.to_string().contains(\"is already used by worktree\") => {\n        // pick another branch or detach\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"// pre-check branch availability\nlet registered = repo.worktrees()?.map(|w| w.ok()).collect::<Vec<_>>();\nanyhow::ensure!(!registered.iter().any(|w| w.branch() == Ok(branch)), \"branch already checked out elsewhere\");","typeGuard":null,"tryCatchPattern":"match add(&repo, &path, branch, base) {\n    Err(e) if e.to_string().contains(\"is already used by worktree\") => use_detached_or_other_branch(),\n    Err(e) if e.to_string().contains(\"Failed to run `git worktree`\") => check_git_installation(),\n    r => r,\n}","preventionTips":["Read the message directly — it is git's own stderr and names the real cause","Ensure git is installed and on PATH in CI/agent environments","Unlock or force-remove worktrees before scripted removal","Avoid checking the same branch out in two worktrees"],"tags":["git","worktree","subprocess","cli"],"backgroundTag":"git-command-failed","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}