Skip to content

Worktree support: git-guard, skill, and implementer agent need updates #7

@tombakerjr

Description

@tombakerjr

Summary

When using git worktrees inside a project directory (.worktrees/), three components of the dev-workflow plugin fail or give incorrect guidance. Discovered during a parallel security fix session on collectors-nexus-backend (QCC-1348 through QCC-1351).

Problem 1: git-guard.py is not worktree-aware

File: hooks/git-guard.py

get_current_branch() (line 19-28) runs bare git rev-parse --abbrev-ref HEAD which always resolves against the CWD (the main repo), not the worktree the command targets.

When committing in a worktree via git -C .worktrees/QCC-1348 commit -m "...", the hook:

  1. Sees git commit in the command
  2. Calls get_current_branch() - runs git rev-parse in main repo CWD - returns main
  3. Blocks the commit with "Cannot commit directly to main/master branch"

The worktree is actually on feature/QCC-1348-remove-eval-user-mapping, but the hook doesn't know that.

Fix needed: Parse the command for -C <path> and pass that path to git rev-parse:

def get_current_branch(command=""):
    """Get current git branch name, respecting -C flag in command."""
    cwd = None
    # Check if command uses git -C <path>
    match = re.search(r'git\s+-C\s+(\S+)', command)
    if match:
        cwd = match.group(1)

    try:
        cmd = ["git"]
        if cwd:
            cmd.extend(["-C", cwd])
        cmd.extend(["rev-parse", "--abbrev-ref", "HEAD"])
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
        return result.stdout.strip() if result.returncode == 0 else None
    except Exception:
        return None

Also handle cd <path> && git commit patterns where the effective CWD changes.

Problem 2: Worktree skill teaches sibling directory pattern

File: skills/using-git-worktrees/SKILL.md

The skill instructs creating worktrees as sibling directories (../repo-feature-name). This conflicts with Claude Code's permission model which scopes file access to the project directory. Sibling worktrees require per-access user approval for Read/Edit/Bash operations since they're outside the project boundary.

Specific lines:

  • Line 65-69: git worktree add ../claude-code-workflows-feature-auth feature-auth
  • Line 73-75: Pattern documented as ../REPO_NAME-BRANCH_NAME
  • Line 239: "Creating worktree in subdirectory of main repo" listed as an anti-pattern -- this is backwards

Fix needed:

  • Change convention to .worktrees/BRANCH_NAME inside the project directory
  • Add .worktrees/ to recommended .gitignore entries
  • Remove or reverse the anti-pattern about subdirectories
  • Update all examples to use the internal worktree path

Problem 3: Implementer agent git -C prohibition is too strict for worktree operations

File: agents/implementer.md

Line 18: "Don't use git -C /path when already in that directory"

When worktrees are inside the project, git -C .worktrees/<name> is the correct and preferred approach for the main orchestrating context. The alternative (cd .worktrees/<name> && git commit) has its own issues:

  • The git-guard hook's subprocess still runs in the original CWD
  • CWD changes in chained commands can cause confusion for agents
  • git -C is explicit and unambiguous about which worktree is targeted

Fix needed: Add an exception: "Prefer cd to the directory first, except when operating on git worktrees from the main context -- use git -C for worktree operations."

Context

During the collectors-nexus-backend session, we worked around these issues by:

  1. Creating worktrees inside .worktrees/ (discovered sibling approach doesn't work)
  2. Using background agents with Read/Edit only (no Bash) to avoid hook issues
  3. Running all git operations from the main context with git -C
  4. The git-guard blocked cd-based commits but allowed git -C commits (the hook only checked bare git rev-parse)

The git -C approach actually worked once we stopped using cd, because git-guard's get_current_branch() returned None (the bare git rev-parse failed or returned the main branch, but the -C path wasn't in the CWD). This was accidental -- the hook should explicitly support worktrees.

Additional: git-guard false positive on issue body text

Meta-bug: the git-guard hook's regex r'git\s+commit' also matches the word "commit" appearing in issue body text passed via heredoc to gh issue create. This blocked the initial attempt to file this very issue. The hook should only match git commands at the start of a command or after &&/;, not inside quoted strings or heredocs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions