sk-git

Git workflow orchestrator: worktree setup, clean commits, finish/PR creation across git-worktrees, git-commit, git-finish.

Best use case

sk-git is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Git workflow orchestrator: worktree setup, clean commits, finish/PR creation across git-worktrees, git-commit, git-finish.

Teams using sk-git should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/sk-git/SKILL.md --create-dirs "https://raw.githubusercontent.com/MichelKerkmeester/opencode--spec-kit-skilled-agent-orchestration/main/.opencode/skills/sk-git/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/sk-git/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How sk-git Compares

Feature / Agentsk-gitStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Git workflow orchestrator: worktree setup, clean commits, finish/PR creation across git-worktrees, git-commit, git-finish.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

<!-- Keywords: git-workflow, git-worktree, conventional-commits, pull-request, commit-hygiene, workspace-isolation, version-control, github, issues, pr-review -->

# Git Workflows - Git Development Orchestrator

Unified workflow guidance across workspace isolation, commit hygiene, and work completion.

## 1. WHEN TO USE

### When to Use This Orchestrator

Use this orchestrator when:
- Starting new git-based work
- Unsure which git skill to use
- Following complete git workflow (setup → work → complete)
- Looking for git best practices (branch naming, commit conventions)

### When NOT to Use

- Simple `git status` or `git log` queries (use Bash directly)
- Non-git version control systems

### Keyword Triggers

`worktree`, `branch`, `commit`, `merge`, `pr`, `pull request`, `git workflow`, `conventional commits`, `finish work`, `integrate changes`, `github`, `issue`, `review`

---

## 2. SMART ROUTING


### Resource Loading Levels

| Level       | When to Load             | Resources                  |
| ----------- | ------------------------ | -------------------------- |
| ALWAYS      | Every skill invocation   | Quick reference baseline   |
| CONDITIONAL | If intent signals match  | Setup/commit/finish docs   |
| ON_DEMAND   | Only on explicit request | Extended patterns/templates|

### Smart Router Pseudocode

The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling.

```python
from pathlib import Path

SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/quick_reference.md"

INTENT_SIGNALS = {
    "WORKSPACE_SETUP": {"weight": 4, "keywords": ["worktree", "workspace", "parallel work"]},
    "COMMIT": {"weight": 4, "keywords": ["commit", "staged", "message", "conventional commit"]},
    "FINISH": {"weight": 4, "keywords": ["finish", "merge", "pr", "pull request", "integrate"]},
    "SHARED_PATTERNS": {"weight": 3, "keywords": ["convention", "pattern", "reference", "branch naming"]},
}

NOISY_SYNONYMS = {
    "WORKSPACE_SETUP": {"dirty workspace": 2.2, "unclean": 1.4, "mixed changes": 1.5},
    "COMMIT": {"half-staged": 2.0, "boundary": 1.4, "split commit": 1.4},
    "FINISH": {"ship": 1.5, "hotfix": 1.6, "trunk": 1.8, "minimal risk": 1.4},
}

UNKNOWN_FALLBACK_CHECKLIST = [
    "Confirm base branch (main/master/trunk)",
    "Confirm whether staged/unstaged changes should be split",
    "Provide required PR policy (squash, template fields, checks)",
    "Confirm hotfix urgency versus cleanup tolerance",
]

RESOURCE_MAP = {
    "WORKSPACE_SETUP": ["references/worktree_workflows.md", "assets/worktree_checklist.md"],
    "COMMIT": ["references/commit_workflows.md", "assets/commit_message_template.md"],
    "FINISH": ["references/finish_workflows.md", "assets/pr_template.md", "references/github_mcp_integration.md"],
    "SHARED_PATTERNS": ["references/shared_patterns.md"],
}

LOADING_LEVELS = {
    "ALWAYS": [DEFAULT_RESOURCE],
    "ON_DEMAND_KEYWORDS": ["full git flow", "all templates", "full reference", "git worktree", "experiment branch", "clean experiment branch", "routing-hardening", "routing-accuracy experiment"],
    "ON_DEMAND": ["references/shared_patterns.md", "assets/commit_message_template.md"],
}

def _task_text(task) -> str:
    return " ".join([
        str(getattr(task, "text", "")),
        str(getattr(task, "query", "")),
        " ".join(getattr(task, "keywords", []) or []),
    ]).lower()

def _guard_in_skill(relative_path: str) -> str:
    resolved = (SKILL_ROOT / relative_path).resolve()
    resolved.relative_to(SKILL_ROOT)
    if resolved.suffix.lower() != ".md":
        raise ValueError(f"Only markdown resources are routable: {relative_path}")
    return resolved.relative_to(SKILL_ROOT).as_posix()

def discover_markdown_resources() -> set[str]:
    docs = []
    for base in RESOURCE_BASES:
        if base.exists():
            docs.extend(p for p in base.rglob("*.md") if p.is_file())
    return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}

def score_intents(task) -> dict[str, float]:
    """Weighted intent scoring from request text and workflow flags."""
    text = _task_text(task)
    scores = {intent: 0.0 for intent in INTENT_SIGNALS}
    for intent, cfg in INTENT_SIGNALS.items():
        for keyword in cfg["keywords"]:
            if keyword in text:
                scores[intent] += cfg["weight"]
    for intent, synonyms in NOISY_SYNONYMS.items():
        for term, weight in synonyms.items():
            if term in text:
                scores[intent] += weight
    if getattr(task, "needs_isolated_workspace", False):
        scores["WORKSPACE_SETUP"] += 4
    if getattr(task, "has_staged_changes", False):
        scores["COMMIT"] += 4
    if getattr(task, "ready_to_integrate", False):
        scores["FINISH"] += 4
    return scores

def select_intents(scores: dict[str, float], task_text: str, ambiguity_delta: float = 1.0, base_max_intents: int = 2, adaptive_max_intents: int = 3) -> list[str]:
    ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
    if not ranked or ranked[0][1] <= 0:
        return ["SHARED_PATTERNS"]

    noisy_hits = sum(1 for term in ["dirty workspace", "half-staged", "hotfix", "minimal risk", "trunk"] if term in (task_text or ""))
    max_intents = adaptive_max_intents if noisy_hits >= 2 else base_max_intents

    selected = [ranked[0][0]]
    for intent, score in ranked[1:]:
        if score <= 0:
            continue
        if (ranked[0][1] - score) <= ambiguity_delta:
            selected.append(intent)
        if len(selected) >= max_intents:
            break
    return selected[:max_intents]

def route_git_resources(task):
    inventory = discover_markdown_resources()
    task_text = _task_text(task)
    scores = score_intents(task)
    intents = select_intents(scores, task_text, ambiguity_delta=1.0)
    loaded = []
    seen = set()

    def load_if_available(relative_path: str) -> None:
        guarded = _guard_in_skill(relative_path)
        if guarded in inventory and guarded not in seen:
            load(guarded)
            loaded.append(guarded)
            seen.add(guarded)

    for relative_path in LOADING_LEVELS["ALWAYS"]:
        load_if_available(relative_path)

    if sum(scores.values()) < 0.5:
        load_if_available("references/shared_patterns.md")
        return {
            "intents": ["SHARED_PATTERNS"],
            "intent_scores": scores,
            "load_level": "UNKNOWN_FALLBACK",
            "needs_disambiguation": True,
            "disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
            "resources": loaded,
        }

    for intent in intents:
        for relative_path in RESOURCE_MAP.get(intent, []):
            load_if_available(relative_path)

    text = _task_text(task)
    if any(keyword in text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
        for relative_path in LOADING_LEVELS["ON_DEMAND"]:
            load_if_available(relative_path)

    if not loaded:
        load_if_available(DEFAULT_RESOURCE)

    return {"intents": intents, "intent_scores": scores, "resources": loaded}
```

---

## 3. HOW IT WORKS

### Workspace Choice Enforcement

**MANDATORY**: The AI must NEVER autonomously decide between creating a git worktree or using the current branch.

The AI must NEVER create a new branch directly with `git branch`, `git checkout` plus `-b`, or `git switch` plus `-c`.

When git workspace triggers are detected (new feature, worktree, isolated workspace, etc.), the AI MUST ask the user to explicitly choose:

| Option                        | Description                              | Best For                        |
| ----------------------------- | ---------------------------------------- | ------------------------------- |
| **A) Create a git worktree**  | Isolated workspace in separate directory | Parallel work, complex features |
| **B) Work on current branch** | No new worktree created                  | Trivial changes, exploration    |

**AI Behavior**: ASK before proceeding, WAIT for explicit selection (A/B), NEVER assume, RESPECT choice throughout. Once chosen, reuse preference for the session unless the user requests a change. If a new branch is needed, create it only through `git worktree add -b ...`.

### Launch-Wrapper Worktrees vs the In-Session Ask-First Rule

The ask-first rule above governs **in-session** decisions: once an AI is running, it must not autonomously create a worktree. That is distinct from `.opencode/bin/worktree-session.sh`, a **launch wrapper** the operator opts into at the shell (e.g. `alias claude='bash /abs/.opencode/bin/worktree-session.sh claude'`). The wrapper runs *before* the AI starts and places each top-level session in its own worktree + branch + isolated MCP databases automatically; orchestrated children (`AI_SESSION_CHILD=1`, or already inside a linked worktree) exec in place. Because the wrapper acts pre-session at operator opt-in, it does not violate the in-session ask-first rule — the operator made the choice by aliasing the launch.

**Deliberate per-session deps override.** The wrapper **symlinks** the shared `node_modules`/`dist` from the main checkout into each worktree and gives each worktree its own MCP DBs (via `SPEC_KIT_DB_DIR` / `SPECKIT_CODE_GRAPH_DB_DIR` / `SPECKIT_IPC_SOCKET_DIR`). This is an intentional exception to the §4 "bare worktree lacks gitignored deps / DBs are a single global instance" guidance: that guidance is about *ad-hoc* worktrees for large reorgs, whereas the wrapper purpose-builds an isolated-but-runnable worktree. Strict-validate and memory reindex still run on `main`, never inside a wrapper worktree.

### Git Development Lifecycle Map

Git development flows through 3 phases:

**Phase 1: Workspace Setup** (Isolate your work)
- **git-worktrees** - Create isolated workspace with short-lived temp branches
- Prevents: Branch juggling, stash chaos, context switching
- Output: Clean workspace ready for focused development
- **See**: [worktree_workflows.md](./references/worktree_workflows.md)

**Phase 2: Work & Commit** (Make clean commits)
- **git-commit** - Analyze changes, filter artifacts, write Conventional Commits
- Prevents: Accidental artifact commits, unclear commit history
- Output: Professional commit history following conventions
- **See**: [commit_workflows.md](./references/commit_workflows.md)

**Phase 3: Complete & Integrate** (Finish the work)
- **git-finish** - Merge, create PR, or discard work (with tests gate)
- Prevents: Incomplete work merged, untested code integrated
- Output: Work successfully integrated or cleanly discarded
- **See**: [finish_workflows.md](./references/finish_workflows.md)

### Phase Transitions
- Setup → Work: Worktree created, ready to code
- Work → Complete: Changes committed, tests passing
- Complete → Setup: Work integrated, start next task

### Skill Selection Decision Tree

**Workspace Setup (Phase 1)**:
- Starting new feature/fix? → **git-worktrees** (isolated workspace)
- Quick fix on current branch? → Skip to Phase 2

**Work & Commit (Phase 2)**:
- Ready to commit? → **git-commit** (analyze, filter, write Conventional Commits)
- No changes yet? → Continue coding

**Complete & Integrate (Phase 3)**:
- Tests pass? → **git-finish** (merge, PR, keep, or discard)
- Tests failing? → Return to Phase 2

### Common Workflow Patterns

**Full Workflow** (new feature):
```
git-worktrees (create workspace) → Code → git-commit (commit changes) → git-finish (integrate)
```

**Quick Fix** (current branch):
```
Code → git-commit (commit fix) → git-finish (integrate)
```

**Parallel Work** (multiple features):
```
git-worktrees (feature A) → Code → git-commit
git-worktrees (feature B) → Code → git-commit
git-finish (feature A) → git-finish (feature B)
```

---

## 4. RULES

### ✅ ALWAYS

1. **Use deterministic conventional commit format** - All commits must follow `type(scope): description` using the commit-message logic defined below
2. **Create worktree for parallel work** - Never work on multiple features in the same worktree
3. **Verify branch is up-to-date** - Pull latest changes before creating PR
4. **Use descriptive worktree-created branch names** - Format: `type/short-description` (e.g., `feat/add-auth`, `fix/login-bug`)
5. **Reference spec folder in commits** - Include spec folder path in commit body when applicable
6. **Clean up after merge** - Delete local and remote feature branches after successful merge
7. **Squash commits for clean history** - Use squash merge for feature branches with many WIP commits
8. **Defer toolchain + DB work to main on large reorgs** - For large rename/reorg, do file/`git mv` ops in the worktree but run the spec-kit toolchain (strict validate, generators, metadata regen) and ALL memory reindex/re-embed on `main` AFTER merge. A bare worktree lacks gitignored deps (`node_modules`/`dist`) and the memory/vector DBs are a single global instance — never per-worktree. See [large_reorg_playbook.md](references/large_reorg_playbook.md).
9. **Scan for gitignored leftovers after a rename wave** - After `git mv` + merge, detect dirs with disk files but 0 tracked files (`git ls-files <dir>` empty and `git status --porcelain --untracked-files=all` clean) and `rm -rf` them — they are stale ignored cruft (`.DS_Store`, `*.log`, `*.pyc`) left behind by `git mv`.
10. **Verify rename history is preserved** - After a rename wave confirm `R`-status (not delete+add) before commit, and after merge confirm the tree has no old+new duplicate folders.
11. **Honor an authorized operator's explicit direct-push directive on a protected branch** - Protected-branch rules (PR-required, verified signatures, code scanning) primarily gate EXTERNAL contributors. When the operator holds bypass rights and explicitly asks to commit/push directly to a protected branch, do a direct `git push` — do NOT default to a PR detour, re-ask whether to use a PR, or frame the bypass / resulting unsigned commit as a problem. Still apply full commit hygiene: scope the commit to the intended files only (a shared or dirty tree may hold concurrent work — never blind `git add -A`), use Conventional Commits, and report plainly that the push bypassed protection. Whether a given operator/repo grants that bypass authority is recorded in operator memory, not in this codebase-agnostic skill.

### Commit Message Logic (AI-Scannable)

Use this logic whenever the AI writes or rewrites commit messages.

1. **Subject format (required)**: `type(scope): summary`
2. **Type selection order (first match wins)**:
   - `merge`: merge commits (`Merge ...`)
   - `release`: version or release subjects (`vX.Y.Z`, `release`)
   - `docs`: docs-only changes or README/CHANGELOG-focused updates
   - `fix`: bug/security/hotfix/error correction
   - `feat`: new behavior, support, or capability
   - `refactor`: internal restructuring without behavior change
   - `test`: test-only updates
   - `chore`: fallback for operational or mixed maintenance work
3. **Scope selection order (first match wins)**:
   - `.opencode/skills/<name>/...` -> `<name>`
   - `AGENTS.md` changes -> `agents`
   - `README.md`-only changes -> `readme`
   - `opencode.json` or `.utcp_config.json` -> `config`
   - `.opencode/agents/...` -> `agents`
   - `.opencode/commands/...` -> `commands`
   - docs-only set -> `docs`
   - fallback -> dominant top-level path or `repo`
4. **Summary normalization**:
   - Keep concise and specific
   - Remove duplicate prefixes like `feat(scope):` from legacy subjects
   - Avoid trailing period
   - Preserve key context tokens (version, skill name, issue id) when relevant
5. **Body format (optional)**:
   - Add only when context is non-obvious
   - Prefer:
     - `Context: <why>`
     - `Changes:` with 1-3 bullets
     - `Refs: <spec-folder|issue|PR>` when available
6. **Determinism rule**:
   - The same diff + metadata should produce the same commit subject every time.

### ❌ NEVER

1. **Force push to main/master** - Protected branches must never receive force pushes
2. **Never create branches directly** - Use `git worktree add -b ...`; never use `git branch`, `git checkout` plus `-b`, or `git switch` plus `-c`
3. **Commit directly to protected branches WITHOUT operator authorization** - Default to feature branches + PRs. EXCEPTION: when the operator has bypass authority on that branch and explicitly directs a direct commit/push, honor it (see ALWAYS #11) — do not force a PR detour.
4. **Leave worktrees uncleaned** - Remove worktree directories after merge
5. **Commit secrets or credentials** - Use environment variables or secret management
6. **Create PRs without description** - Always include context, changes, and testing notes
7. **Merge without CI passing** - Wait for all checks to complete
8. **Rebase public/shared branches** - Only rebase local, unpushed commits

### ⚠️ ESCALATE IF

1. **Merge conflicts cannot be auto-resolved** - Complex conflicts require human decision on which changes to keep
2. **GitHub MCP returns authentication errors** - Token may be expired or permissions insufficient
3. **Worktree directory is locked or corrupted** - May require manual cleanup with `git worktree prune`
4. **Force push to protected branch is requested** - This requires explicit approval and understanding of consequences
5. **CI/CD pipeline fails repeatedly** - May indicate infrastructure issues beyond code problems
6. **Branch divergence exceeds 50 commits** - Large divergence suggests need for incremental merging strategy
7. **Submodule conflicts detected** - Submodule updates require careful coordination
8. **Strict-validate run inside a bare worktree** - Its exit code is meaningless (missing gitignored deps may make it silently no-op on zero files). Re-run on `main` post-merge before trusting any result. See [large_reorg_playbook.md](references/large_reorg_playbook.md).

---

## 5. REFERENCES

### Core Workflows
| Document | Purpose | Key Insight |
|----------|---------|-------------|
| [worktree_workflows.md](references/worktree_workflows.md) | 7-step workspace creation | Directory selection, branch strategies, large-reorg caveats (§8b) |
| [large_reorg_playbook.md](references/large_reorg_playbook.md) | Step-ordered large rename/reorg runbook | Worktree-only renames; toolchain + DB run on main post-merge |
| [commit_workflows.md](references/commit_workflows.md) | 6-step commit workflow | Artifact filtering, Conventional Commits, scoped-staging discipline for a dirty tree / unrelated WIP (§3 Step 7) |
| [finish_workflows.md](references/finish_workflows.md) | 5-step completion flow | PR creation, cleanup, merge |
| [shared_patterns.md](references/shared_patterns.md) | Reusable git patterns | Error recovery, conflict resolution, rename-heavy / large-reorg merge verification (§10) |
| [quick_reference.md](references/quick_reference.md) | Command cheat sheet | Common operations |
| [github_mcp_integration.md](references/github_mcp_integration.md) | GitHub MCP remote ops | PRs, issues, CI/CD via Code Mode |

### Assets
| Asset | Purpose | Usage |
|-------|---------|-------|
| [worktree_checklist.md](assets/worktree_checklist.md) | Worktree creation checklist | Pre-flight verification |
| [commit_message_template.md](assets/commit_message_template.md) | Commit format guide | Conventional Commits |
| [pr_template.md](assets/pr_template.md) | PR description template | Consistent PR format |

---

## 6. SUCCESS CRITERIA

### Workspace Setup Complete
- Workspace prepared in the selected mode (`git worktree` or current branch)
- If a worktree was selected, it was created in the correct directory (`.worktrees/` or user-specified)
- Any worktree-created branch naming follows convention (`type/short-description`)
- User confirmed workspace choice (worktree/current branch)

### Commit Complete
- All changes reviewed and categorized
- Artifacts filtered out (build files, coverage, etc.)
- Commit message follows Conventional Commits format
- Only public-value files staged

### Integration Complete
- Tests pass before merge/PR
- PR description includes context, changes, and testing notes
- Branch up-to-date with base branch
- Worktree cleaned up after merge (if used)
- Local and remote feature branches deleted

### Quality Gates

| Gate | Criteria | Blocking |
|------|----------|----------|
| **Pre-commit** | Artifacts excluded, message formatted | Yes |
| **Pre-merge** | Tests pass, branch up-to-date | Yes |
| **Pre-PR** | Description complete, CI passing | Yes |
| **Post-merge** | Worktree removed, branches cleaned | No |

---

## 7. INTEGRATION POINTS

### Framework Integration

This skill operates within the behavioral framework defined in [AGENTS.md](../../../AGENTS.md).

Key integrations:
- **Gate 2**: Skill routing via `skill_advisor.py`
- **Gate 3**: File modifications require spec folder question per AGENTS.md Gate 3 (HARD BLOCK)
- **Tool Routing**: Per AGENTS.md Section 6 decision tree
- **Continuity**: `/speckit:resume` is the recovery surface; canonical packet context is read from `handover.md -> _memory.continuity -> spec docs`

### Continuity Integration

Use canonical packet continuity for context recovery first, then use Spec Kit Memory MCP only when packet-native sources are exhausted:

```text
// Recover the active packet before planning git work
/speckit:resume
// Recovery order: handover.md -> _memory.continuity -> spec docs

// If packet-native sources are exhausted, use Spec Kit Memory MCP for wider lookups
memory_search({ query: "branch strategy decisions", includeContent: true })

// After major commits or workflow completion
// Save context with: /memory:save or "save context to [spec-folder]"
```

**Best Practices**:
- Use `/speckit:resume` at session start to recover active packet context
- Prefer `handover.md`, `_memory.continuity`, and canonical spec docs before broader memory queries
- Save context after significant commits or before ending a session
- Reference spec folder in commit messages for traceability

---

## 8. REFERENCES AND RELATED RESOURCES

The router discovers reference, asset, and script docs dynamically. Start with `references/quick_reference.md`, `references/worktree_workflows.md`, `references/commit_workflows.md`, `references/finish_workflows.md`, `references/github_mcp_integration.md`, `references/shared_patterns.md`, `assets/commit_message_template.md`, then load task-specific resources from `references/`, templates from `assets/`, and automation from `scripts/` when present.

### Manual Testing Playbook

Manual testing scenarios for this skill live in `manual_testing_playbook/manual_testing_playbook.md` (root index) plus 22 per-feature sub-files under `manual_testing_playbook/<NN>--<topic>/<NNN>-<scenario>.md`. Run scenarios via `bash .opencode/skills/sk-doc/scripts/validate_document.py manual_testing_playbook/manual_testing_playbook.md` for structural validation; execute scenarios in opencode/Claude/Codex sessions for behavioral verification.

Related skills: `system-spec-kit` for packet recovery and continuity, and `sk-doc` for PR, release, and documentation quality.

Related Skills

We are still matching the closest adjacent skills for this page. In the meantime, continue through the full directory.